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
00028
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
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
if(!tag.
AttachFrame(frame))
return NULL;
00112 }
00113 frame->GetField(ID3FN_TEXT)->Set(text.c_str());
00114
00115
return frame;
00116 }
00117
00119
00120
ID3_Frame* id3::v2::hasArtist(
const ID3_TagImpl& tag)
00121 {
00122
ID3_Frame* fp =
NULL;
00123 (fp = tag.
Find(ID3FID_LEADARTIST)) ||
00124 (fp = tag.
Find(ID3FID_BAND)) ||
00125 (fp = tag.
Find(ID3FID_CONDUCTOR)) ||
00126 (fp = tag.
Find(ID3FID_COMPOSER));
00127
return fp;
00128 }
00129
00130 String id3::v2::getArtist(
const ID3_TagImpl& tag)
00131 {
00132
ID3_Frame* frame = hasArtist(tag);
00133
return getString(frame, ID3FN_TEXT);
00134 }
00135
00136
ID3_Frame* id3::v2::setArtist(
ID3_TagImpl& tag, String text)
00137 {
00138 removeArtists(tag);
00139
return setFrameText(tag, ID3FID_LEADARTIST, text);
00140 }
00141
00142 size_t id3::v2::removeArtists(
ID3_TagImpl& tag)
00143 {
00144 size_t numRemoved = 0;
00145
ID3_Frame* frame =
NULL;
00146
00147
while ((frame = hasArtist(tag)) !=
NULL)
00148 {
00149 frame = tag.
RemoveFrame(frame);
00150
delete frame;
00151 numRemoved++;
00152 }
00153
00154
return numRemoved;
00155 }
00156
00158
00159
ID3_Frame* id3::v2::hasAlbum(
const ID3_TagImpl& tag)
00160 {
00161
ID3_Frame* frame = tag.
Find(ID3FID_ALBUM);
00162
return(frame);
00163 }
00164
00165 String id3::v2::getAlbum(
const ID3_TagImpl& tag)
00166 {
00167
return getFrameText(tag, ID3FID_ALBUM);
00168 }
00169
00170
ID3_Frame* id3::v2::setAlbum(
ID3_TagImpl& tag, String text)
00171 {
00172
return setFrameText(tag, ID3FID_ALBUM, text);
00173 }
00174
00175 size_t id3::v2::removeAlbums(
ID3_TagImpl& tag)
00176 {
00177
return removeFrames(tag, ID3FID_ALBUM);
00178 }
00179
00181
00182
ID3_Frame* id3::v2::hasTitle(
const ID3_TagImpl& tag)
00183 {
00184
ID3_Frame* frame = tag.
Find(ID3FID_TITLE);
00185
return(frame);
00186 }
00187
00188 String id3::v2::getTitle(
const ID3_TagImpl& tag)
00189 {
00190
return getFrameText(tag, ID3FID_TITLE);
00191 }
00192
00193
ID3_Frame* id3::v2::setTitle(
ID3_TagImpl& tag, String text)
00194 {
00195
return setFrameText(tag, ID3FID_TITLE, text);
00196 }
00197
00198 size_t id3::v2::removeTitles(
ID3_TagImpl& tag)
00199 {
00200
return removeFrames(tag, ID3FID_TITLE);
00201 }
00202
00204
00205
ID3_Frame* id3::v2::hasYear(
const ID3_TagImpl& tag)
00206 {
00207
ID3_Frame* frame = tag.
Find(ID3FID_YEAR);
00208
return(frame);
00209 }
00210
00211 String id3::v2::getYear(
const ID3_TagImpl& tag)
00212 {
00213
return getFrameText(tag, ID3FID_YEAR);
00214 }
00215
00216
ID3_Frame* id3::v2::setYear(
ID3_TagImpl& tag, String text)
00217 {
00218
return setFrameText(tag, ID3FID_YEAR, text);
00219 }
00220
00221 size_t id3::v2::removeYears(
ID3_TagImpl& tag)
00222 {
00223
return removeFrames(tag, ID3FID_YEAR);
00224 }
00225
00227
00228
ID3_Frame* id3::v2::hasV1Comment(
const ID3_TagImpl& tag)
00229 {
00230
ID3_Frame* frame =
NULL;
00231 (frame = tag.
Find(ID3FID_COMMENT, ID3FN_DESCRIPTION, STR_V1_COMMENT_DESC)) ||
00232 (frame = tag.
Find(ID3FID_COMMENT, ID3FN_DESCRIPTION,
"" )) ||
00233 (frame = tag.
Find(ID3FID_COMMENT));
00234
return(frame);
00235 }
00236
00237
ID3_Frame* id3::v2::hasComment(
const ID3_TagImpl& tag)
00238 {
00239
ID3_Frame* frame = tag.
Find(ID3FID_COMMENT);
00240
return(frame);
00241 }
00242
00243 String id3::v2::getV1Comment(
const ID3_TagImpl& tag)
00244 {
00245
ID3_Frame* frame;
00246 (frame = tag.
Find(ID3FID_COMMENT, ID3FN_DESCRIPTION, STR_V1_COMMENT_DESC)) ||
00247 (frame = tag.
Find(ID3FID_COMMENT, ID3FN_DESCRIPTION,
"" )) ||
00248 (frame = tag.
Find(ID3FID_COMMENT));
00249
return getString(frame, ID3FN_TEXT);
00250 }
00251
00252 String id3::v2::getComment(
const ID3_TagImpl& tag, String desc)
00253 {
00254
ID3_Frame* frame = tag.
Find(ID3FID_COMMENT, ID3FN_DESCRIPTION, desc.c_str());
00255
return getString(frame, ID3FN_TEXT);
00256 }
00257
00258
ID3_Frame* id3::v2::setComment(
ID3_TagImpl& tag, String text, String desc,
00259 String lang)
00260 {
00261 ID3D_NOTICE(
"id3::v2::setComment: trying to find frame with description = " << desc );
00262
ID3_Frame* frame =
NULL;
00263
00264
for (
ID3_TagImpl::iterator iter = tag.
begin(); iter != tag.
end(); ++iter)
00265 {
00266 frame = *iter;
00267
if (frame ==
NULL)
00268 {
00269
continue;
00270 }
00271
if (frame->GetID() ==
ID3FID_COMMENT)
00272 {
00273 String tmpDesc = getString(frame, ID3FN_DESCRIPTION);
00274
if (tmpDesc == desc)
00275 {
00276 ID3D_NOTICE(
"id3::v2::setComment: found frame with description = " << desc );
00277
break;
00278 }
00279 }
00280 frame =
NULL;
00281 }
00282
if (frame ==
NULL)
00283 {
00284 ID3D_NOTICE(
"id3::v2::setComment: creating new comment frame" );
00285 frame =
new ID3_Frame(ID3FID_COMMENT);
00286
if(!tag.
AttachFrame(frame))
return NULL;
00287 }
00288
if (!frame)
00289 {
00290 ID3D_WARNING(
"id3::v2::setComment: ack! no frame" );
00291 }
00292
else
00293 {
00294 frame->GetField(ID3FN_LANGUAGE)->Set(lang.c_str());
00295 frame->GetField(ID3FN_DESCRIPTION)->Set(desc.c_str());
00296 frame->GetField(ID3FN_TEXT)->Set(text.c_str());
00297 }
00298
00299
return frame;
00300 }
00301
00302
00303 size_t id3::v2::removeAllComments(
ID3_TagImpl& tag)
00304 {
00305
return removeFrames(tag, ID3FID_COMMENT);
00306 }
00307
00308
00309 size_t id3::v2::removeComments(
ID3_TagImpl& tag, String desc)
00310 {
00311 size_t numRemoved = 0;
00312
00313
for (
ID3_TagImpl::iterator iter = tag.
begin(); iter != tag.
end(); ++iter)
00314 {
00315
ID3_Frame* frame = *iter;
00316
if (frame ==
NULL)
00317 {
00318
continue;
00319 }
00320
if (frame->GetID() ==
ID3FID_COMMENT)
00321 {
00322
00323
00324 String tmpDesc = getString(frame, ID3FN_DESCRIPTION);
00325
if (tmpDesc == desc)
00326 {
00327 frame = tag.
RemoveFrame(frame);
00328
delete frame;
00329 numRemoved++;
00330 }
00331 }
00332 }
00333
00334
return numRemoved;
00335 }
00336
00338
00339
ID3_Frame* id3::v2::hasTrack(
const ID3_TagImpl& tag)
00340 {
00341
ID3_Frame* frame = tag.
Find(ID3FID_TRACKNUM);
00342
return(frame);
00343 }
00344
00345 String id3::v2::getTrack(
const ID3_TagImpl& tag)
00346 {
00347
return getFrameText(tag, ID3FID_TRACKNUM);
00348 }
00349
00350 size_t id3::v2::getTrackNum(
const ID3_TagImpl& tag)
00351 {
00352 String sTrack = getTrack(tag);
00353 return ::atoi(sTrack.c_str());
00354 }
00355
00356
ID3_Frame* id3::v2::setTrack(
ID3_TagImpl& tag, uchar trk, uchar ttl)
00357 {
00358
ID3_Frame* frame =
NULL;
00359 String track = toString((size_t)trk);
00360
if (ttl > 0)
00361 {
00362 track +=
"/";
00363 track += toString((size_t)ttl);
00364 }
00365 setFrameText(tag, ID3FID_TRACKNUM, track);
00366
00367
return frame;
00368 }
00369
00370 size_t id3::v2::removeTracks(
ID3_TagImpl& tag)
00371 {
00372
return removeFrames(tag, ID3FID_TRACKNUM);
00373 }
00374
00376
00377
ID3_Frame* id3::v2::hasGenre(
const ID3_TagImpl& tag)
00378 {
00379
ID3_Frame* frame = tag.
Find(ID3FID_CONTENTTYPE);
00380
return(frame);
00381 }
00382
00383 String id3::v2::getGenre(
const ID3_TagImpl& tag)
00384 {
00385
return getFrameText(tag, ID3FID_CONTENTTYPE);
00386 }
00387
00388 size_t id3::v2::getGenreNum(
const ID3_TagImpl& tag)
00389 {
00390 String sGenre = getGenre(tag);
00391 size_t ulGenre = 0xFF;
00392 size_t size = sGenre.size();
00393
00394
00395
00396 size_t i = 0;
00397
if (i < size && size && sGenre[i] ==
'(')
00398 {
00399 ++i;
00400
while (i < size && isdigit(sGenre[i]))
00401 {
00402 ++i;
00403 }
00404
if (i < size && sGenre[i] ==
')')
00405 {
00406
00407 ulGenre =
min(0xFF, atoi(&sGenre[1]));
00408 }
00409 }
00410
00411
return ulGenre;
00412 }
00413
00414
ID3_Frame* id3::v2::setGenre(
ID3_TagImpl& tag, size_t genre)
00415 {
00416 String sGenre =
"(";
00417 sGenre += toString(genre) +
")";
00418
return setFrameText(tag, ID3FID_CONTENTTYPE, sGenre);
00419 }
00420
00421 size_t id3::v2::removeGenres(
ID3_TagImpl& tag)
00422 {
00423
return removeFrames(tag, ID3FID_CONTENTTYPE);
00424 }
00425
00427
00428
ID3_Frame* id3::v2::hasLyrics(
const ID3_TagImpl& tag)
00429 {
00430
ID3_Frame* frame = tag.
Find(ID3FID_UNSYNCEDLYRICS);
00431
return(frame);
00432 }
00433
00434 String id3::v2::getLyrics(
const ID3_TagImpl& tag)
00435 {
00436
return getFrameText(tag, ID3FID_UNSYNCEDLYRICS);
00437 }
00438
00439
ID3_Frame* id3::v2::setLyrics(
ID3_TagImpl& tag, String text, String desc,
00440 String lang)
00441 {
00442
ID3_Frame* frame =
NULL;
00443
00444
for (
ID3_TagImpl::iterator iter = tag.
begin(); iter != tag.
end(); ++iter)
00445 {
00446 frame = *iter;
00447
if (frame ==
NULL)
00448 {
00449
continue;
00450 }
00451
if (frame->GetID() ==
ID3FID_COMMENT)
00452 {
00453 String tmpDesc = getString(frame, ID3FN_DESCRIPTION);
00454
if (tmpDesc == desc)
00455 {
00456
break;
00457 }
00458 }
00459 frame =
NULL;
00460 }
00461
if (frame ==
NULL)
00462 {
00463 frame =
new ID3_Frame(ID3FID_UNSYNCEDLYRICS);
00464
if(!tag.
AttachFrame(frame))
return NULL;
00465 }
00466 frame->GetField(ID3FN_LANGUAGE)->Set(lang.c_str());
00467 frame->GetField(ID3FN_DESCRIPTION)->Set(desc.c_str());
00468 frame->GetField(ID3FN_TEXT)->Set(text.c_str());
00469
00470
return frame;
00471 }
00472
00473 size_t id3::v2::removeLyrics(
ID3_TagImpl& tag)
00474 {
00475
return removeFrames(tag, ID3FID_UNSYNCEDLYRICS);
00476 }
00477
00478 String id3::v2::getLyricist(
const ID3_TagImpl& tag)
00479 {
00480
return getFrameText(tag, ID3FID_LYRICIST);
00481 }
00482
00483
ID3_Frame* id3::v2::setLyricist(
ID3_TagImpl& tag, String text)
00484 {
00485
return setFrameText(tag, ID3FID_LYRICIST, text);
00486 }
00487
00488 size_t id3::v2::removeLyricists(
ID3_TagImpl& tag)
00489 {
00490
return removeFrames(tag, ID3FID_LYRICIST);
00491 }
00492
00494
00495
ID3_Frame* id3::v2::hasSyncLyrics(
const ID3_TagImpl& tag, String lang, String desc)
00496 {
00497
ID3_Frame* frame=
NULL;
00498 (frame = tag.
Find(ID3FID_SYNCEDLYRICS, ID3FN_LANGUAGE, lang)) ||
00499 (frame = tag.
Find(ID3FID_SYNCEDLYRICS, ID3FN_DESCRIPTION, desc));
00500
return(frame);
00501 }
00502
00503
ID3_Frame* id3::v2::setSyncLyrics(
ID3_TagImpl& tag, BString data,
00504 ID3_TimeStampFormat format, String desc,
00505 String lang, ID3_ContentType type)
00506 {
00507
ID3_Frame* frame =
NULL;
00508
00509
00510 (frame = tag.
Find(ID3FID_SYNCEDLYRICS, ID3FN_LANGUAGE, lang)) ||
00511 (frame = tag.
Find(ID3FID_SYNCEDLYRICS, ID3FN_DESCRIPTION, desc));
00512
00513
if (!frame)
00514 {
00515 frame =
new ID3_Frame(ID3FID_SYNCEDLYRICS);
00516
if(!tag.
AttachFrame(frame))
return NULL;
00517 }
00518 frame->GetField(ID3FN_LANGUAGE)->Set(lang.c_str());
00519 frame->GetField(ID3FN_DESCRIPTION)->Set(desc.c_str());
00520 frame->GetField(ID3FN_TIMESTAMPFORMAT)->Set(format);
00521 frame->GetField(ID3FN_CONTENTTYPE)->Set(type);
00522 frame->GetField(ID3FN_DATA)->Set(data.data(), data.size());
00523
00524
return frame;
00525 }
00526
00527 BString id3::v2::getSyncLyrics(
const ID3_TagImpl& tag, String lang, String desc)
00528 {
00529
00530
ID3_Frame* frame =
NULL;
00531 (frame = tag.
Find(ID3FID_SYNCEDLYRICS, ID3FN_LANGUAGE, lang)) ||
00532 (frame = tag.
Find(ID3FID_SYNCEDLYRICS, ID3FN_DESCRIPTION, desc)) ||
00533 (frame = tag.
Find(ID3FID_SYNCEDLYRICS));
00534
00535
00536
ID3_Field* fld = frame->GetField(ID3FN_DATA);
00537
return BString(reinterpret_cast<const BString::value_type *>(fld->
GetRawBinary()), fld->
Size());
00538 }
00539