diff options
Diffstat (limited to 'Src/Plugins/Input/in_mp3/ID3v2.cpp')
-rw-r--r-- | Src/Plugins/Input/in_mp3/ID3v2.cpp | 654 |
1 files changed, 654 insertions, 0 deletions
diff --git a/Src/Plugins/Input/in_mp3/ID3v2.cpp b/Src/Plugins/Input/in_mp3/ID3v2.cpp new file mode 100644 index 00000000..04600232 --- /dev/null +++ b/Src/Plugins/Input/in_mp3/ID3v2.cpp @@ -0,0 +1,654 @@ +#include "ID3v2.h" +#include "id3.h" +#include "config.h" +#include "api__in_mp3.h" +#include "../Agave/AlbumArt/svc_albumArtProvider.h" +#include "../nu/AutoChar.h" +#include "../nu/AutoWide.h" +#include <strsafe.h> + +static inline const wchar_t *IncSafe(const wchar_t *val, int x) +{ + while (x--) + { + if (val && *val) + val++; + } + return val; +} + +extern const wchar_t *id3v1_genres[]; +extern size_t numGenres; + +ID3v2::ID3v2() +{ + hasData=false; + dirty=false; +} + +int ID3v2::Decode(const void *data, size_t len) +{ + if (!config_parse_id3v2 || !data) + { + hasData=false; + return 0; + } + + id3v2.Parse((uchar *)data, (uchar *)data+ID3_TAGHEADERSIZE); + if (id3v2.NumFrames() > 0) + { + hasData=true; + return 0; + } + else + return 1; +} + +// return -1 for empty, 1 for OK, 0 for "don't understand tag name" +int ID3v2::GetString(const char *tag, wchar_t *data, int dataLen) +{ + if (!_stricmp(tag, "title")) + return ID3_GetTagText(&id3v2, ID3FID_TITLE, data, dataLen)?1:-1; + else if (!_stricmp(tag, "album")) + return ID3_GetTagText(&id3v2, ID3FID_ALBUM, data, dataLen)?1:-1; + else if (!_stricmp(tag, "artist")) + return ID3_GetTagText(&id3v2, ID3FID_LEADARTIST, data, dataLen)?1:-1; + else if (!_stricmp(tag, "albumartist")) + { + if (!ID3_GetTagText(&id3v2, ID3FID_BAND, data, dataLen) && !ID3_GetUserText(&id3v2, L"ALBUM ARTIST", data, dataLen) && !ID3_GetUserText(&id3v2, L"ALBUMARTIST", data, dataLen)) + return ID3_GetUserText(&id3v2, L"Band", data, dataLen)?1:-1; + else + return 1; + } + else if (!_stricmp(tag, "comment")) + return ID3_GetComment(&id3v2, data, dataLen)?1:-1; + else if (!_stricmp(tag, "year")) + { + if (!ID3_GetTagText(&id3v2, ID3FID_RECORDINGTIME, data, dataLen)) + return ID3_GetTagText(&id3v2, ID3FID_YEAR, data, dataLen)?1:-1; + else + return 1; + } + else if (!_stricmp(tag, "composer")) + return ID3_GetTagText(&id3v2, ID3FID_COMPOSER, data, dataLen)?1:-1; + else if (!_stricmp(tag, "replaygain_track_gain")) + return ID3_GetUserText(&id3v2, L"replaygain_track_gain", data, dataLen)?1:-1; + else if (!_stricmp(tag, "replaygain_album_gain")) + return ID3_GetUserText(&id3v2, L"replaygain_album_gain", data, dataLen)?1:-1; + else if (!_stricmp(tag, "replaygain_track_peak")) + return ID3_GetUserText(&id3v2, L"replaygain_track_peak", data, dataLen)?1:-1; + else if (!_stricmp(tag, "replaygain_album_peak")) + return ID3_GetUserText(&id3v2, L"replaygain_album_peak", data, dataLen)?1:-1; + else if (!_stricmp(tag, "genre")) + { + data[0] = 0; + if (ID3_GetTagText(&id3v2, ID3FID_CONTENTTYPE, data, dataLen)) + { + wchar_t *tmp = data; + while (tmp && *tmp == ' ') tmp++; + if (tmp && (*tmp == '(' || (*tmp >= '0' && *tmp <= '9'))) // both (%d) and %d forms + { + int noparam = 0; + if (*tmp == '(') tmp++; + else noparam = 1; + size_t genre_index = _wtoi(tmp); + int cnt = 0; + while (tmp && *tmp >= '0' && *tmp <= '9') cnt++, tmp++; + while (tmp && *tmp == ' ') tmp++; + + if (tmp && (((!*tmp && noparam) || (!noparam && *tmp == ')')) && cnt > 0)) + { + if (genre_index < numGenres) + StringCchCopyW(data, dataLen, id3v1_genres[genre_index]); + } + } + return 1; + } + return -1; + } + else if (!_stricmp(tag, "track")) + return ID3_GetTagText(&id3v2, ID3FID_TRACKNUM, data, dataLen)?1:-1; + else if (!_stricmp(tag, "disc")) + return ID3_GetTagText(&id3v2, ID3FID_PARTINSET, data, dataLen)?1:-1; + else if (!_stricmp(tag, "bpm")) + return ID3_GetTagText(&id3v2, ID3FID_BPM, data, dataLen)?1:-1; + else if (!_stricmp(tag, "rating")) + return ID3_GetRating(&id3v2, data, dataLen)?1:-1; + else if (!_stricmp(tag, "conductor")) + return ID3_GetTagText(&id3v2, ID3FID_CONDUCTOR, data, dataLen)?1:-1; + else if (!_stricmp(tag, "key")) + return ID3_GetTagText(&id3v2, ID3FID_KEY, data, dataLen)?1:-1; + else if (!_stricmp(tag, "mood")) + return ID3_GetTagText(&id3v2, ID3FID_MOOD, data, dataLen)?1:-1; + else if (!_stricmp(tag, "subtitle")) + return ID3_GetTagText(&id3v2, ID3FID_SUBTITLE, data, dataLen)?1:-1; + else if (!_stricmp(tag, "lyricist")) + return ID3_GetTagText(&id3v2, ID3FID_LYRICIST, data, dataLen)?1:-1; + else if (!_stricmp(tag, "ISRC")) + return ID3_GetTagText(&id3v2, ID3FID_ISRC, data, dataLen)?1:-1; + else if (!_stricmp(tag, "media")) + return ID3_GetTagText(&id3v2, ID3FID_MEDIATYPE, data, dataLen)?1:-1; + else if (!_stricmp(tag, "remixing")) + return ID3_GetTagText(&id3v2, ID3FID_MIXARTIST, data, dataLen)?1:-1; + else if (!_stricmp(tag, "originalartist")) + return ID3_GetTagText(&id3v2, ID3FID_ORIGARTIST, data, dataLen)?1:-1; + else if (!_stricmp(tag, "encoder")) + return ID3_GetTagText(&id3v2, ID3FID_ENCODERSETTINGS, data, dataLen)?1:-1; + else if (!_stricmp(tag, "publisher")) + return ID3_GetTagText(&id3v2, ID3FID_PUBLISHER, data, dataLen)?1:-1; + else if (!_stricmp(tag, "copyright")) + return ID3_GetTagText(&id3v2, ID3FID_COPYRIGHT, data, dataLen)?1:-1; + else if (!_stricmp(tag, "compilation")) + return ID3_GetTagText(&id3v2, ID3FID_COMPILATION, data, dataLen)?1:-1; + else if (!_stricmp(tag, "url")) + return ID3_GetTagUrl(&id3v2, ID3FID_WWWUSER, data, dataLen)?1:-1; + else if (!_stricmp(tag, "GracenoteFileID")) + return ID3_GetGracenoteTagID(&id3v2, data, dataLen)?1:-1; + else if (!_stricmp(tag, "GracenoteExtData")) + { + if (!ID3_GetUserText(&id3v2, L"GN_ExtData", data, dataLen)) + return ID3_GetUserText(&id3v2, L"GN/ExtData", data, dataLen)?1:-1; + else + return 1; + } + else if (!_stricmp(tag, "tool")) + return ID3_GetTagText(&id3v2, ID3FID_ENCODEDBY, data, dataLen)?1:-1; + else if (!_stricmp(tag, "pregap")) + { + data[0] = 0; + // first, check for stupid iTunSMPB TXXX frame + wchar_t gaps[128] = L""; + const wchar_t *itr = ID3_GetComment(&id3v2, L"iTunSMPB", gaps, 128); + if (itr && *itr) + { + itr = IncSafe(itr, 9); + unsigned int prepad = wcstoul(itr, 0, 16); + StringCchPrintfW(data, dataLen, L"%u", prepad); + return 1; + } + return -1; + } + else if (!_stricmp(tag, "postgap")) + { + data[0] = 0; + // first, check for stupid iTunSMPB TXXX frame + wchar_t gaps[128] = L""; + const wchar_t *itr = ID3_GetComment(&id3v2, L"iTunSMPB", gaps, 128); + if (itr && *itr) + { + itr = IncSafe(itr, 18); + unsigned int postpad = wcstoul(itr, 0, 16); + StringCchPrintfW(data, dataLen, L"%u", postpad); + return 1; + } + return -1; + } + else if (!_stricmp(tag, "numsamples")) + { + data[0] = 0; + // first, check for stupid iTunSMPB TXXX frame + wchar_t gaps[128] = L""; + const wchar_t *itr = ID3_GetComment(&id3v2, L"iTunSMPB", gaps, 128); + if (itr && *itr) + { + itr = IncSafe(itr, 27); + unsigned __int64 samples = wcstoul(itr, 0, 16); + StringCchPrintfW(data, dataLen, L"%I64u", samples); + return 1; + } + return -1; + } + else if (!_stricmp(tag, "endoffset")) + { + data[0] = 0; + // first, check for stupid iTunSMPB TXXX frame + wchar_t gaps[128] = L""; + const wchar_t *itr = ID3_GetComment(&id3v2, L"iTunSMPB", gaps, 128); + if (itr && *itr) + { + itr = IncSafe(itr, 53); + unsigned __int32 endoffset = wcstoul(itr, 0, 16); + StringCchPrintfW(data, dataLen, L"%I32u", endoffset); + return 1; + } + return -1; + } + else if (!_stricmp(tag, "category")) + { + return ID3_GetTagText(&id3v2, ID3FID_CONTENTGROUP, data, dataLen)?1:-1; + } + // things generally added by Musicbrainz tagging (either specific or additional) + else if (!_stricmp(tag, "acoustid") || !_stricmp(tag, "acoustid_id")) + { + return ID3_GetUserText(&id3v2, L"Acoustid Id", data, dataLen)?1:-1; + } + else if (!_stricmp(tag, "acoustid_fingerprint")) + { + return ID3_GetUserText(&id3v2, L"Acoustid Fingerprint", data, dataLen)?1:-1; + } + else if (!_stricmp(tag, "asin")) + { + return ID3_GetUserText(&id3v2, L"ASIN", data, dataLen)?1:-1; + } + else if (!_stricmp(tag, "barcode")) + { + return ID3_GetUserText(&id3v2, L"BARCODE", data, dataLen)?1:-1; + } + else if (!_stricmp(tag, "catalognumber")) + { + return ID3_GetUserText(&id3v2, L"CATALOGNUMBER", data, dataLen)?1:-1; + } + else if (!_stricmp(tag, "script")) + { + return ID3_GetUserText(&id3v2, L"SCRIPT", data, dataLen)?1:-1; + } + else if (!_stricmp(tag, "musicbrainz_recordingid")) // (track id) + { + return ID3_GetMusicbrainzRecordingID(&id3v2, data, dataLen)?1:-1; + } + else if (!_stricmp(tag, "musicbrainz_trackid")) // TODO not working (album track id) + { + return ID3_GetUserText(&id3v2, L"MusicBrainz Release Track Id", data, dataLen)?1:-1; + } + else if (!_stricmp(tag, "musicbrainz_albumid")) + { + return ID3_GetUserText(&id3v2, L"MusicBrainz Album Id", data, dataLen)?1:-1; + } + else if (!_stricmp(tag, "musicbrainz_artistid")) + { + return ID3_GetUserText(&id3v2, L"MusicBrainz Artist Id", data, dataLen)?1:-1; + } + else if (!_stricmp(tag, "musicbrainz_albumartistid")) + { + return ID3_GetUserText(&id3v2, L"MusicBrainz Album Artist Id", data, dataLen)?1:-1; + } + else if (!_stricmp(tag, "musicbrainz_releasestatus") || !_stricmp(tag, "musicbrainz_albumstatus")) + { + return ID3_GetUserText(&id3v2, L"MusicBrainz Album Status", data, dataLen)?1:-1; + } + else if (!_stricmp(tag, "musicbrainz_releasetype") || !_stricmp(tag, "musicbrainz_albumtype")) + { + return ID3_GetUserText(&id3v2, L"MusicBrainz Album Type", data, dataLen)?1:-1; + } + else if (!_stricmp(tag, "musicbrainz_releasecountry") || !_stricmp(tag, "musicbrainz_albumcountry")) + { + return ID3_GetUserText(&id3v2, L"MusicBrainz Album Release Country", data, dataLen)?1:-1; + } + else if (!_stricmp(tag, "musicbrainz_releasegroupid") || !_stricmp(tag, "musicbrainz_albumgroupid")) + { + return ID3_GetUserText(&id3v2, L"MusicBrainz Release Group Id", data, dataLen)?1:-1; + } + else + { + return 0; + } +} + +void ID3v2::add_set_latin_id3v2_frame(ID3_FrameID id, const wchar_t *c) +{ + ID3_Frame *f = id3v2.Find(id); + if (!c) + { + if (f) + id3v2.RemoveFrame(f); + } + else + { + if (f) + { + SetFrameEncoding(f, ENCODING_FORCE_ASCII); + AutoChar temp(c); //AutoChar temp(c, 28591); // todo: benski> changed back to local to keep old winamp tagged files working + f->Field(ID3FN_URL).SetLocal(temp); //f->Field(ID3FN_TEXT).SetLatin(temp);// todo: benski> changed back to local to keep old winamp tagged files working + } + else + { + f = new ID3_Frame(id); + SetFrameEncoding(f, ENCODING_FORCE_ASCII); + AutoChar temp(c); //AutoChar temp(c, 28591); // todo: benski> changed back to local to keep old winamp tagged files working + f->Field(ID3FN_URL).SetLocal(temp); //f->Field(ID3FN_TEXT).SetLatin(temp);// todo: benski> changed back to local to keep old winamp tagged files working + id3v2.AddFrame(f, TRUE); + } + } +} + +int ID3v2::SetString(const char *tag, const wchar_t *data) +{ + if (!_stricmp(tag, "artist")) + add_set_id3v2_frame(ID3FID_LEADARTIST, data); + else if (!_stricmp(tag, "album")) + add_set_id3v2_frame(ID3FID_ALBUM, data); + else if (!_stricmp(tag, "albumartist")) + { + add_set_id3v2_frame(ID3FID_BAND, data); + if (!data || !*data) // if we're deleting the field + { + ID3_AddUserText(&id3v2, L"ALBUM ARTIST", data); // delete this alternate field also, or it's gonna look like it didn't "take" with a fb2k file + ID3_AddUserText(&id3v2, L"ALBUMARTIST", data); // delete this alternate field also, or it's gonna look like it didn't "take" with an mp3tag file + ID3_AddUserText(&id3v2, L"Band", data); // delete this alternate field also, or it's gonna look like it didn't "take" with an audacity file + } + } + else if (!_stricmp(tag, "comment")) + ID3_AddSetComment(&id3v2, data); + else if (!_stricmp(tag, "title")) + add_set_id3v2_frame(ID3FID_TITLE, data); + else if (!_stricmp(tag, "year")) + { + add_set_id3v2_frame(ID3FID_YEAR, data); + if (id3v2.version >= 4) // work around the fact that our id3 code doesn't handle versioning like this too well + add_set_id3v2_frame(ID3FID_RECORDINGTIME, data); + else + add_set_id3v2_frame(ID3FID_RECORDINGTIME, (wchar_t *)0); + } + else if (!_stricmp(tag, "genre")) + add_set_id3v2_frame(ID3FID_CONTENTTYPE, data); + else if (!_stricmp(tag, "track")) + add_set_id3v2_frame(ID3FID_TRACKNUM, data); + else if (!_stricmp(tag, "disc")) + add_set_id3v2_frame(ID3FID_PARTINSET, data); + else if (!_stricmp(tag, "bpm")) + add_set_id3v2_frame(ID3FID_BPM, data); + else if (!_stricmp(tag, "rating")) + ID3_AddSetRating(&id3v2, data); + else if (!_stricmp(tag, "tool")) + add_set_id3v2_frame(ID3FID_ENCODEDBY, data); + else if (!_stricmp(tag, "composer")) + add_set_id3v2_frame(ID3FID_COMPOSER, data); + else if (!_stricmp(tag, "replaygain_track_gain")) + ID3_AddUserText(&id3v2, L"replaygain_track_gain", data, ENCODING_FORCE_ASCII); + else if (!_stricmp(tag, "replaygain_track_peak")) + ID3_AddUserText(&id3v2, L"replaygain_track_peak", data, ENCODING_FORCE_ASCII); + else if (!_stricmp(tag, "replaygain_album_gain")) + ID3_AddUserText(&id3v2, L"replaygain_album_gain", data, ENCODING_FORCE_ASCII); + else if (!_stricmp(tag, "replaygain_album_peak")) + ID3_AddUserText(&id3v2, L"replaygain_album_peak", data, ENCODING_FORCE_ASCII); + else if (!_stricmp(tag, "originalartist")) + add_set_id3v2_frame(ID3FID_ORIGARTIST, data); + else if (!_stricmp(tag, "encoder")) + add_set_id3v2_frame(ID3FID_ENCODERSETTINGS, data); + else if (!_stricmp(tag, "publisher")) + add_set_id3v2_frame(ID3FID_PUBLISHER, data); + else if (!_stricmp(tag, "copyright")) + add_set_id3v2_frame(ID3FID_COPYRIGHT, data); + else if (!_stricmp(tag, "compilation")) + add_set_id3v2_frame(ID3FID_COMPILATION, data); + else if (!_stricmp(tag, "remixing")) + add_set_id3v2_frame(ID3FID_MIXARTIST, data); + else if (!_stricmp(tag, "ISRC")) + add_set_id3v2_frame(ID3FID_ISRC, data); + else if (!_stricmp(tag, "url")) + add_set_latin_id3v2_frame(ID3FID_WWWUSER, data); // TODO: we should %## escape invalid characters + //add_set_id3v2_frame(ID3FID_WWWUSER, data); + else if (!_stricmp(tag, "GracenoteFileID")) + ID3_AddSetGracenoteTagID(&id3v2, data); + else if (!_stricmp(tag, "GracenoteExtData")) + { + ID3_AddUserText(&id3v2, L"GN_ExtData", data, ENCODING_FORCE_ASCII); + ID3_AddUserText(&id3v2, L"GN_ExtData",0); // delete this alternate field also + } + else if (!_stricmp(tag, "category")) + add_set_id3v2_frame(ID3FID_CONTENTGROUP, data); + else + return 0; + hasData=true; + dirty=true; + return 1; +} + +void ID3v2::add_set_id3v2_frame(ID3_FrameID id, const wchar_t *c) +{ + ID3_Frame *f = id3v2.Find(id); + if (!c || !*c) + { + if (f) + id3v2.RemoveFrame(f); + } + else + { + if (f) + { + SetFrameEncoding(f); + f->Field(ID3FN_TEXT).SetUnicode(c); + } + else + { + f = new ID3_Frame(id); + SetFrameEncoding(f); + f->Field(ID3FN_TEXT).SetUnicode(c); + id3v2.AddFrame(f, TRUE); + } + } +} + +uint32_t ID3v2::EncodeSize() +{ + if (!hasData) + return 0; // simple :) + + return (uint32_t)id3v2.Size(); +} + +int ID3v2::Encode(const void *data, size_t len) +{ + id3v2.Render((uchar *)data); + return 0; +} + +static bool NameToAPICType(const wchar_t *name, int &num) +{ + if (!name || !*name) // default to cover + num=0x3; + else if (!_wcsicmp(name, L"fileicon")) // 32x32 pixels 'file icon' (PNG only) + num=0x1; + else if (!_wcsicmp(name, L"icon")) // Other file icon + num=0x2; + else if (!_wcsicmp(name, L"cover")) // Cover (front) + num=0x3; + else if (!_wcsicmp(name, L"back")) // Cover (back) + num=0x4; + else if (!_wcsicmp(name, L"leaflet")) // Leaflet page + num=0x5; + else if (!_wcsicmp(name, L"media")) // Media (e.g. lable side of CD) + num=0x6; + else if (!_wcsicmp(name, L"leadartist")) //Lead artist/lead performer/soloist + num=0x7; + else if (!_wcsicmp(name, L"artist")) // Artist/performer + num=0x8; + else if (!_wcsicmp(name, L"conductor")) // Conductor + num=0x9; + else if (!_wcsicmp(name, L"band")) // Band/Orchestra + num=0xA; + else if (!_wcsicmp(name, L"composer")) // Composer + num=0xB; + else if (!_wcsicmp(name, L"lyricist")) // Lyricist/text writer + num=0xC; + else if (!_wcsicmp(name, L"location")) // Recording Location + num=0xD; + else if (!_wcsicmp(name, L"recording")) // During recording + num=0xE; + else if (!_wcsicmp(name, L"performance")) // During performance + num=0xF; + else if (!_wcsicmp(name, L"preview")) // Movie/video screen capture + num=0x10; + else if (!_wcsicmp(name, L"fish")) // A bright coloured fish + num=0x11; + else if (!_wcsicmp(name, L"illustration")) // Illustration + num=0x12; + else if (!_wcsicmp(name, L"artistlogo")) // Band/artist logotype + num=0x13; + else if (!_wcsicmp(name, L"publisherlogo")) // Publisher/Studio logotype + num=0x14; + else + return false; + return true; +} + +int ID3v2::GetAlbumArt(const wchar_t *type, void **bits, size_t *len, wchar_t **mimeType) +{ + int pictype = 0; + if (NameToAPICType(type, pictype)) + { + // try to get our specific picture type + ID3_Frame *frame = id3v2.Find(ID3FID_PICTURE, ID3FN_PICTURETYPE, pictype); + + if (!frame && pictype == 3) // if not, just try a generic one + { + frame = id3v2.Find(ID3FID_PICTURE); + /*benski> CUT! + if (frame) + { + ID3_Field &field = frame->Field(ID3FN_PICTURETYPE); + if (field.Get()) + frame=0; + }*/ + } + + if (frame) + { + char *fulltype = ID3_GetString(frame, ID3FN_MIMETYPE); + char *type = 0; + if (fulltype && *fulltype) + { + type = strchr(fulltype, '/'); + } + + if (type && *type) + { + type++; + + char *type2 = strchr(type, '/'); + if (type2 && *type2) type2++; + else type2 = type; + + int typelen = MultiByteToWideChar(CP_ACP, 0, type2, -1, 0, 0); + *mimeType = (wchar_t *)WASABI_API_MEMMGR->sysMalloc(typelen * sizeof(wchar_t)); + MultiByteToWideChar(CP_ACP, 0, type2, -1, *mimeType, typelen); + free(fulltype); + } + else + { + // attempt to work out a mime type from known 'invalid' values + if (fulltype && *fulltype) + { + if (!strcmpi(fulltype, "png") || !strcmpi(fulltype, "bmp") || + !strcmpi(fulltype, "jpg") || !strcmpi(fulltype, "jpeg") || + !strcmpi(fulltype, "gif")) + { + int typelen = MultiByteToWideChar(CP_ACP, 0, fulltype, -1, 0, 0);// + 6; + *mimeType = (wchar_t*)WASABI_API_MEMMGR->sysMalloc(typelen * sizeof(wchar_t)); + MultiByteToWideChar(CP_ACP, 0, fulltype, -1, *mimeType, typelen); + CharLowerBuff(*mimeType, typelen); + free(fulltype); + fulltype = 0; + } + if (0 != fulltype) + { + free(fulltype); + fulltype = 0; + } + } + else + { + *mimeType = 0; // unknown! + } + } + + ID3_Field &field = frame->Field(ID3FN_DATA); + *len = field.Size(); + *bits = WASABI_API_MEMMGR->sysMalloc(*len); + field.Get((uchar *)*bits, *len); + return ALBUMARTPROVIDER_SUCCESS; + } + } + return ALBUMARTPROVIDER_FAILURE; +} + +int ID3v2::SetAlbumArt(const wchar_t *type, void *bits, size_t len, const wchar_t *mimeType) +{ + int pictype; + if (NameToAPICType(type, pictype)) + { + // try to get our specific picture type + ID3_Frame *frame = id3v2.Find(ID3FID_PICTURE, ID3FN_PICTURETYPE, pictype); + + if (!frame && pictype == 3) // if not, just try a generic one + { + frame = id3v2.Find(ID3FID_PICTURE); + /* benski> cut + if (frame) + { + ID3_Field &field = frame->Field(ID3FN_PICTURETYPE); + if (field.Get()) + frame=0; + }*/ + } + bool newFrame=false; + if (!frame) + { + frame = new ID3_Frame(ID3FID_PICTURE); + newFrame = true; + } + + if (frame) + { + wchar_t mt[32] = {L"image/jpeg"}; + if (mimeType) + { + if (wcsstr(mimeType, L"/") != 0) + { + StringCchCopyW(mt, 32, mimeType); + } + else + { + StringCchPrintfW(mt, 32, L"image/%s", mimeType); + } + } + + frame->Field(ID3FN_MIMETYPE).SetLatin(AutoChar(mt, 28591)); + frame->Field(ID3FN_PICTURETYPE).Set(pictype); + frame->Field(ID3FN_DESCRIPTION).Clear(); + frame->Field(ID3FN_DATA).Set((uchar *)bits, len); + if (newFrame) + id3v2.AddFrame(frame, TRUE); + dirty=1; + return ALBUMARTPROVIDER_SUCCESS; + } + } + return ALBUMARTPROVIDER_FAILURE; +} + +int ID3v2::DeleteAlbumArt(const wchar_t *type) +{ + int pictype; + if (NameToAPICType(type, pictype)) + { + // try to get our specific picture type + ID3_Frame *frame = id3v2.Find(ID3FID_PICTURE, ID3FN_PICTURETYPE, pictype); + + if (!frame && pictype == 3) // if not, just try a generic one + { + frame = id3v2.Find(ID3FID_PICTURE); + /* benski> cut + if (frame) + { + ID3_Field &field = frame->Field(ID3FN_PICTURETYPE); + if (field.Get()) + frame=0; + } + */ + } + if (frame) + { + id3v2.RemoveFrame(frame); + dirty=1; + return ALBUMARTPROVIDER_SUCCESS; + } + } + return ALBUMARTPROVIDER_FAILURE; +} + +void ID3v2::Clear() +{ + dirty=1; + hasData=false; + id3v2.Clear(); +}
\ No newline at end of file |