1 #include "stdafx.h" 2 #include "TagLibHelper.h" 3 #include "taglib/mp4file.h" 4 #include "taglib/mp4coverart.h" 5 #include "taglib/flacfile.h" 6 #include "taglib/flacpicture.h" 7 #include "taglib/mpegfile.h" 8 #include "Common.h" 9 #include "FilePathHelper.h" 10 #include "taglib/attachedpictureframe.h" 11 #include "taglib/id3v2tag.h" 12 #include "taglib/id3v1tag.h" 13 #include "taglib/apefile.h" 14 #include "taglib/wavfile.h" 15 #include "taglib/mpcfile.h" 16 #include "taglib/opusfile.h" 17 #include "taglib/wavpackfile.h" 18 #include "taglib/vorbisfile.h" 19 #include "taglib/trueaudiofile.h" 20 #include "taglib/aifffile.h" 21 #include "taglib/asffile.h" 22 #include "taglib/tpropertymap.h" 23 #include "AudioCommon.h" 24 #include "taglib/apetag.h" 25 #include "taglib/fileref.h" 26 #include "taglib/speexfile.h" 27 #include "taglib/unsynchronizedlyricsframe.h" 28 #include "taglib/id3v2frame.h" 29 #include "taglib/popularimeterframe.h" 30 31 32 using namespace TagLib; 33 34 #define STR_MP4_COVER_TAG "covr" 35 #define STR_MP4_LYRICS_TAG "----:com.apple.iTunes:Lyrics" 36 #define STR_ASF_COVER_TAG "WM/Picture" 37 #define STR_APE_COVER_TAG "COVER ART (FRONT)" 38 #define STR_ID3V2_LYRIC_TAG "USLT" 39 #define STR_ID3V2_RATEING_TAG "POPM" 40 #define STR_FLAC_LYRIC_TAG "LYRICS" 41 #define STR_ASF_LYRIC_TAG "LYRICS" 42 #define STR_APE_CUE_TAG "CUESHEET" 43 44 //将taglib中的字符串转换成wstring类型。 45 //由于taglib将所有非unicode编码全部作为Latin编码处理,因此无法正确处理本地代码页 46 //这里将Latin编码的字符串按本地代码页处理 47 static wstring TagStringToWstring(const String& str, bool to_local) 48 { 49 wstring result; 50 if (to_local && str.isLatin1()) 51 result = CCommon::StrToUnicode(str.to8Bit(), CodeType::ANSI); 52 else 53 result = str.toWString(); 54 return result; 55 } 56 57 static void SongInfoToTag(const SongInfo& song_info, Tag* tag) 58 { 59 if (tag != nullptr) 60 { 61 tag->setTitle(song_info.title); 62 tag->setArtist(song_info.artist); 63 tag->setAlbum(song_info.album); 64 tag->setGenre(song_info.genre); 65 tag->setTrack(song_info.track); 66 tag->setComment(song_info.comment); 67 tag->setYear(song_info.year); 68 } 69 } 70 71 static bool IsStringNumber(wstring str, int num) 72 { 73 if (!str.empty() && str.front() == L'(') 74 str = str.substr(1); 75 if (!str.empty() && str.back() == L')') 76 str.pop_back(); 77 if (CCommon::StrIsNumber(str)) 78 { 79 num = _wtoi(str.c_str()); 80 return true; 81 } 82 return false; 83 } 84 85 static void TagToSongInfo(SongInfo& song_info, Tag* tag, bool to_local) 86 { 87 if (tag != nullptr) 88 { 89 song_info.title = TagStringToWstring(tag->title(), to_local); 90 song_info.artist = TagStringToWstring(tag->artist(), to_local); 91 song_info.album = TagStringToWstring(tag->album(), to_local); 92 song_info.genre = TagStringToWstring(tag->genre(), to_local); 93 int genre_num{}; 94 if (IsStringNumber(song_info.genre, genre_num)) 95 { 96 song_info.genre = CAudioCommon::GetGenre(static_cast<BYTE>(genre_num)); 97 } 98 99 song_info.year = tag->year(); 100 song_info.track = tag->track(); 101 song_info.comment = TagStringToWstring(tag->comment(), to_local); 102 } 103 } 104 105 //将文件内容读取到ByteVector 106 static void FileToByteVector(ByteVector& data, const std::wstring& file_path) 107 { 108 std::ifstream file{ file_path, std::ios::binary | std::ios::in }; 109 if (file.fail()) 110 return; 111 112 //获取文件长度 113 file.seekg(0, file.end); 114 size_t length = file.tellg(); 115 file.seekg(0, file.beg); 116 117 data.clear(); 118 data.resize(static_cast<unsigned int>(length)); 119 120 file.read(data.data(), length); 121 122 file.close(); 123 } 124 125 int GetPicType(const wstring& mimeType) 126 { 127 int type{ -1 }; 128 if (mimeType == L"image/jpeg" || mimeType == L"image/jpg") 129 type = 0; 130 else if (mimeType == L"image/png") 131 type = 1; 132 else if (mimeType == L"image/gif") 133 type = 2; 134 else if (mimeType == L"image/bmp") 135 type = 3; 136 else 137 type = -1; 138 return type; 139 } 140 141 static void GetId3v2AlbumCover(ID3v2::Tag* id3v2, string& cover_contents, int& type) 142 { 143 if (id3v2 != nullptr) 144 { 145 auto pic_frame_list = id3v2->frameListMap()["APIC"]; 146 if (!pic_frame_list.isEmpty()) 147 { 148 ID3v2::AttachedPictureFrame* frame = dynamic_cast<TagLib::ID3v2::AttachedPictureFrame*>(pic_frame_list.front()); 149 if (frame != nullptr) 150 { 151 auto pic_data = frame->picture(); 152 //获取专辑封面 153 cover_contents.assign(pic_data.data(), pic_data.size()); 154 wstring img_type = frame->mimeType().toCWString(); 155 type = GetPicType(img_type); 156 } 157 } 158 } 159 } 160 161 static void DeleteId3v2AlbumCover(ID3v2::Tag* id3v2tag) 162 { 163 if (id3v2tag != nullptr) 164 { 165 auto pic_frame_list = id3v2tag->frameListMap()["APIC"]; 166 if (!pic_frame_list.isEmpty()) 167 { 168 for (auto frame : pic_frame_list) 169 id3v2tag->removeFrame(frame); 170 } 171 } 172 } 173 174 static void WriteId3v2AlbumCover(ID3v2::Tag* id3v2tag, const wstring& album_cover_path) 175 { 176 if (id3v2tag != nullptr) 177 { 178 //读取图片文件 179 ByteVector pic_data; 180 FileToByteVector(pic_data, album_cover_path); 181 //向音频文件写入图片文件 182 ID3v2::AttachedPictureFrame* pic_frame = new ID3v2::AttachedPictureFrame(); 183 pic_frame->setPicture(pic_data); 184 pic_frame->setType(ID3v2::AttachedPictureFrame::FrontCover); 185 wstring ext = CFilePathHelper(album_cover_path).GetFileExtension(); 186 pic_frame->setMimeType(L"image/" + ext); 187 id3v2tag->addFrame(pic_frame); 188 } 189 } 190 191 192 static void GetApeTagAlbumCover(APE::Tag* tag, string& cover_contents, int& type) 193 { 194 if (tag != nullptr) 195 { 196 auto item_list_map = tag->itemListMap(); 197 auto pic_item = item_list_map[STR_APE_COVER_TAG]; 198 auto pic_data = pic_item.binaryData(); 199 if (!pic_data.isEmpty()) 200 { 201 cover_contents.assign(pic_data.data(), pic_data.size()); 202 203 size_t index{}; 204 index = cover_contents.find('\0'); 205 std::string pic_desc; 206 if (index != std::string::npos) 207 { 208 pic_desc = cover_contents.substr(0, index); 209 cover_contents = cover_contents.substr(index + 1); 210 } 211 212 if (!pic_desc.empty()) 213 { 214 std::string img_type; 215 index = pic_desc.rfind('.'); 216 if (index != std::string::npos && index < pic_desc.size() - 1) 217 { 218 img_type = pic_desc.substr(index + 1); 219 img_type = "image/" + img_type; 220 type = GetPicType(CCommon::ASCIIToUnicode(img_type)); 221 } 222 } 223 } 224 } 225 } 226 227 static void WriteApeTagAlbumCover(APE::Tag* tag, const wstring& album_cover_path, bool remove_exist) 228 { 229 if (remove_exist) 230 { 231 tag->removeItem(STR_APE_COVER_TAG); 232 } 233 234 if (!album_cover_path.empty()) 235 { 236 ByteVector pic_data; 237 FileToByteVector(pic_data, album_cover_path); 238 239 ByteVector pic_item_data; 240 pic_item_data = "Cover Art (Front)."; 241 wstring file_type = CFilePathHelper(album_cover_path).GetFileExtension(); 242 for (wchar_t ch : file_type) 243 pic_item_data.append(static_cast<char>(ch)); 244 pic_item_data.append('\0'); 245 pic_item_data.append(pic_data); 246 247 APE::Item pic_item(STR_APE_COVER_TAG, pic_item_data, true); 248 tag->setItem(STR_APE_COVER_TAG, pic_item); 249 } 250 } 251 252 static void WriteXiphCommentAlbumCover(Ogg::XiphComment* tag, const wstring& album_cover_path, bool remove_exist) 253 { 254 //先删除专辑封面 255 if (remove_exist) 256 { 257 tag->removeAllPictures(); 258 } 259 260 if (!album_cover_path.empty()) 261 { 262 ByteVector pic_data; 263 FileToByteVector(pic_data, album_cover_path); 264 FLAC::Picture* newpic = new FLAC::Picture(); 265 newpic->setType(FLAC::Picture::FrontCover); 266 newpic->setData(pic_data); 267 wstring ext = CFilePathHelper(album_cover_path).GetFileExtension(); 268 newpic->setMimeType(L"image/" + ext); 269 tag->addPicture(newpic); 270 } 271 } 272 273 274 static void GetXiphCommentAlbumCover(Ogg::XiphComment* tag, string& cover_contents, int& type) 275 { 276 const auto& cover_list = tag->pictureList(); 277 if (!cover_list.isEmpty()) 278 { 279 auto pic = cover_list.front(); 280 if (pic != nullptr) 281 { 282 const auto& pic_data = pic->data(); 283 //获取专辑封面 284 cover_contents.assign(pic_data.data(), pic_data.size()); 285 286 wstring img_type = pic->mimeType().toCWString(); 287 type = GetPicType(img_type); 288 } 289 } 290 } 291 292 static wstring GetId3v2Lyric(ID3v2::Tag* id3v2) 293 { 294 wstring lyrics; 295 if (id3v2 != nullptr) 296 { 297 auto frame_list_map = id3v2->frameListMap(); 298 auto lyric_frame = frame_list_map[STR_ID3V2_LYRIC_TAG]; 299 if (!lyric_frame.isEmpty()) 300 lyrics = lyric_frame.front()->toString().toWString(); 301 } 302 return lyrics; 303 } 304 305 306 static void WriteId3v2Lyric(ID3v2::Tag* id3v2, const wstring& lyric_contents) 307 { 308 if (id3v2 != nullptr) 309 { 310 //先删除歌词帧 311 auto lyric_frame_list = id3v2->frameListMap()[STR_ID3V2_LYRIC_TAG]; 312 if (!lyric_frame_list.isEmpty()) 313 { 314 for (auto frame : lyric_frame_list) 315 id3v2->removeFrame(frame); 316 } 317 318 if (!lyric_contents.empty()) 319 { 320 //写入歌词帧 321 ID3v2::UnsynchronizedLyricsFrame* lyric_frame = new ID3v2::UnsynchronizedLyricsFrame(); 322 lyric_frame->setText(lyric_contents.c_str()); 323 id3v2->addFrame(lyric_frame); 324 } 325 } 326 } 327 328 329 template<class T> 330 void GetTagPropertyMap(T* tag, std::map<wstring, wstring>& property_map) 331 { 332 if (tag != nullptr) 333 { 334 auto properties = tag->properties(); 335 for (const auto& prop : properties) 336 { 337 wstring key = prop.first.toWString(); 338 wstring value = TagStringToWstring(prop.second.toString(L";"), true); 339 auto iter = property_map.find(key); 340 if (iter == property_map.end()) 341 property_map[key] = value; 342 else if (iter->second.empty()) 343 iter->second = value; 344 } 345 } 346 } 347 348 //解析Windows资源管理器设置的分级信息 349 static int ParseAudioRating(int rate_raw) 350 { 351 //使用Windows资源管理器设置了分级后,POPM字段的内容为以下格式: 352 //Windows Media Player 9 Series rating=196 counter=0 353 //其中rating后面的数字为分级,rating与分级的对应关系如下所示 354 /* 355 rating | 分级 356 ---------|------------ 357 255 | 5 358 196 | 4 359 128 | 3 360 64 | 2 361 1 | 1 362 */ 363 364 //根据分级转换成1~5星 365 if (rate_raw == 1) 366 return 1; 367 else if (rate_raw <= 64) 368 return 2; 369 else if (rate_raw <= 128) 370 return 3; 371 else if (rate_raw <= 196) 372 return 4; 373 else if (rate_raw <= 255) 374 return 5; 375 return 0; 376 } 377 378 static int GenerateAudioRating(int rate) 379 { 380 switch (rate) 381 { 382 case 1: 383 return 1; 384 case 2: 385 return 64; 386 case 3: 387 return 128; 388 case 4: 389 return 196; 390 case 5: 391 return 255; 392 default: 393 return 0; 394 } 395 } 396 397 static int GetId3v2Rating(ID3v2::Tag* id3v2) 398 { 399 if (id3v2 != nullptr) 400 { 401 auto frame_list_map = id3v2->frameListMap(); 402 auto rate_frame = frame_list_map[STR_ID3V2_RATEING_TAG]; 403 if (!rate_frame.isEmpty()) 404 { 405 ID3v2::PopularimeterFrame* pFrame = dynamic_cast<ID3v2::PopularimeterFrame*>(rate_frame.front()); 406 if (pFrame != nullptr) 407 { 408 int rate_raw = pFrame->rating(); 409 return ParseAudioRating(rate_raw); 410 } 411 } 412 } 413 return 0; 414 } 415 416 static void WriteId3v2Rating(ID3v2::Tag* id3v2, int rate) 417 { 418 if (id3v2 != nullptr) 419 { 420 auto frameListMap = id3v2->frameListMap(); 421 422 //先删除POPM帧 423 auto rate_frame_list = id3v2->frameListMap()[STR_ID3V2_RATEING_TAG]; 424 if (!rate_frame_list.isEmpty()) 425 { 426 for (auto frame : rate_frame_list) 427 id3v2->removeFrame(frame); 428 } 429 430 ID3v2::PopularimeterFrame* rate_frame = new ID3v2::PopularimeterFrame(); 431 int rate_raw = GenerateAudioRating(rate); 432 rate_frame->setRating(rate_raw); 433 id3v2->addFrame(rate_frame); 434 } 435 } 436 437 /////////////////////////////////////////////////////////////////////////////////// 438 /////////////////////////////////////////////////////////////////////////////////// 439 /////////////////////////////////////////////////////////////////////////////////// 440 441 442 CTagLibHelper::CTagLibHelper() 443 { 444 } 445 446 CTagLibHelper::~CTagLibHelper() 447 { 448 } 449 450 string CTagLibHelper::GetM4aAlbumCover(const wstring& file_path, int& type) 451 { 452 string cover_contents; 453 MP4::File file(file_path.c_str()); 454 auto tag = file.tag(); 455 if (tag != nullptr) 456 { 457 auto cover_item = tag->item(STR_MP4_COVER_TAG).toCoverArtList(); 458 if (!cover_item.isEmpty()) 459 { 460 const auto& pic_data = cover_item.front().data(); 461 //获取专辑封面 462 cover_contents.assign(pic_data.data(), pic_data.size()); 463 464 //获取封面格式 465 switch (cover_item.front().format()) 466 { 467 case MP4::CoverArt::JPEG: 468 type = 0; 469 break; 470 case MP4::CoverArt::PNG: 471 type = 1; 472 break; 473 case MP4::CoverArt::BMP: 474 type = 3; 475 break; 476 case MP4::CoverArt::GIF: 477 type = 2; 478 break; 479 default: 480 type = -1; 481 break; 482 } 483 } 484 } 485 return cover_contents; 486 } 487 488 string CTagLibHelper::GetFlacAlbumCover(const wstring& file_path, int& type) 489 { 490 string cover_contents; 491 FLAC::File file(file_path.c_str()); 492 const auto& cover_list = file.pictureList(); 493 if (!cover_list.isEmpty()) 494 { 495 auto pic = cover_list.front(); 496 if (pic != nullptr) 497 { 498 const auto& pic_data = pic->data(); 499 //获取专辑封面 500 cover_contents.assign(pic_data.data(), pic_data.size()); 501 502 wstring img_type = pic->mimeType().toCWString(); 503 type = GetPicType(img_type); 504 } 505 } 506 return cover_contents; 507 } 508 509 string CTagLibHelper::GetMp3AlbumCover(const wstring& file_path, int& type) 510 { 511 string cover_contents; 512 MPEG::File file(file_path.c_str()); 513 auto id3v2 = file.ID3v2Tag(); 514 GetId3v2AlbumCover(id3v2, cover_contents, type); 515 return cover_contents; 516 } 517 518 string CTagLibHelper::GetAsfAlbumCover(const wstring& file_path, int& type) 519 { 520 string cover_contents; 521 ASF::File file(file_path.c_str()); 522 auto tag = file.tag(); 523 if (tag != nullptr) 524 { 525 ASF::AttributeList attr = tag->attribute("WM/Picture"); 526 if (!attr.isEmpty()) 527 { 528 ASF::Picture picture = attr.front().toPicture(); 529 auto pic_data = picture.picture(); 530 cover_contents.assign(pic_data.data(), pic_data.size()); 531 wstring img_type = picture.mimeType().toCWString(); 532 type = GetPicType(img_type); 533 } 534 } 535 return cover_contents; 536 } 537 538 string CTagLibHelper::GetWavAlbumCover(const wstring& file_path, int& type) 539 { 540 string cover_contents; 541 RIFF::WAV::File file(file_path.c_str()); 542 auto id3v2 = file.ID3v2Tag(); 543 GetId3v2AlbumCover(id3v2, cover_contents, type); 544 return cover_contents; 545 } 546 547 string CTagLibHelper::GetTtaAlbumCover(const wstring& file_path, int& type) 548 { 549 string cover_contents; 550 TrueAudio::File file(file_path.c_str()); 551 auto id3v2 = file.ID3v2Tag(); 552 GetId3v2AlbumCover(id3v2, cover_contents, type); 553 return cover_contents; 554 } 555 556 string CTagLibHelper::GetApeAlbumCover(const wstring& file_path, int& type) 557 { 558 string cover_contents; 559 APE::File file(file_path.c_str()); 560 auto tag = file.APETag(); 561 GetApeTagAlbumCover(tag, cover_contents, type); 562 return cover_contents; 563 } 564 565 566 string CTagLibHelper::GetOggAlbumCover(const wstring& file_path, int& type) 567 { 568 string cover_contents; 569 Ogg::Vorbis::File file(file_path.c_str()); 570 auto tag = file.tag(); 571 if (tag != nullptr) 572 { 573 GetXiphCommentAlbumCover(tag, cover_contents, type); 574 } 575 return cover_contents; 576 } 577 578 string CTagLibHelper::GetOpusAlbumCover(const wstring& file_path, int& type) 579 { 580 string cover_contents; 581 Ogg::Opus::File file(file_path.c_str()); 582 auto tag = file.tag(); 583 if (tag != nullptr) 584 { 585 GetXiphCommentAlbumCover(tag, cover_contents, type); 586 } 587 return cover_contents; 588 } 589 590 string CTagLibHelper::GetSpxAlbumCover(const wstring& file_path, int& type) 591 { 592 string cover_contents; 593 Ogg::Speex::File file(file_path.c_str()); 594 auto tag = file.tag(); 595 if (tag != nullptr) 596 { 597 GetXiphCommentAlbumCover(tag, cover_contents, type); 598 } 599 return cover_contents; 600 } 601 602 string CTagLibHelper::GetAiffAlbumCover(const wstring& file_path, int& type) 603 { 604 string cover_contents; 605 RIFF::AIFF::File file(file_path.c_str()); 606 auto id3v2 = file.tag(); 607 GetId3v2AlbumCover(id3v2, cover_contents, type); 608 return cover_contents; 609 610 } 611 612 string CTagLibHelper::GetMpcAlbumCover(const wstring& file_path, int& type) 613 { 614 string cover_contents; 615 MPC::File file(file_path.c_str()); 616 auto ape_tag = file.APETag(); 617 GetApeTagAlbumCover(ape_tag, cover_contents, type); 618 return cover_contents; 619 } 620 621 string CTagLibHelper::GetWavePackAlbumCover(const wstring& file_path, int& type) 622 { 623 string cover_contents; 624 WavPack::File file(file_path.c_str()); 625 auto ape_tag = file.APETag(); 626 GetApeTagAlbumCover(ape_tag, cover_contents, type); 627 return cover_contents; 628 } 629 630 void CTagLibHelper::GetFlacTagInfo(SongInfo& song_info) 631 { 632 FLAC::File file(song_info.file_path.c_str()); 633 if (file.hasID3v1Tag()) 634 song_info.tag_type |= T_ID3V1; 635 if (file.hasID3v2Tag()) 636 song_info.tag_type |= T_ID3V2; 637 auto tag = file.tag(); 638 if (tag != nullptr) 639 { 640 TagToSongInfo(song_info, tag, true); 641 } 642 } 643 644 void CTagLibHelper::GetM4aTagInfo(SongInfo& song_info) 645 { 646 MP4::File file(song_info.file_path.c_str()); 647 if (file.hasMP4Tag()) 648 song_info.tag_type |= T_MP4; 649 auto tag = file.tag(); 650 if (tag != nullptr) 651 { 652 TagToSongInfo(song_info, tag, false); 653 } 654 } 655 656 void CTagLibHelper::GetMpegTagInfo(SongInfo& song_info) 657 { 658 MPEG::File file(song_info.file_path.c_str()); 659 if (file.hasID3v1Tag()) 660 song_info.tag_type |= T_ID3V1; 661 if (file.hasID3v2Tag()) 662 song_info.tag_type |= T_ID3V2; 663 if (file.hasAPETag()) 664 song_info.tag_type |= T_APE; 665 666 auto tag = file.tag(); 667 if (tag != nullptr) 668 { 669 TagToSongInfo(song_info, tag, true); 670 } 671 } 672 673 void CTagLibHelper::GetAsfTagInfo(SongInfo& song_info) 674 { 675 ASF::File file(song_info.file_path.c_str()); 676 auto tag = file.tag(); 677 if (tag != nullptr) 678 { 679 TagToSongInfo(song_info, tag, false); 680 } 681 } 682 683 void CTagLibHelper::GetApeTagInfo(SongInfo& song_info) 684 { 685 APE::File file(song_info.file_path.c_str()); 686 if (file.hasID3v1Tag()) 687 song_info.tag_type |= T_ID3V1; 688 if (file.hasAPETag()) 689 song_info.tag_type |= T_APE; 690 691 auto tag = file.tag(); 692 if (tag != nullptr) 693 { 694 TagToSongInfo(song_info, tag, true); 695 } 696 } 697 698 void CTagLibHelper::GetWavTagInfo(SongInfo& song_info) 699 { 700 RIFF::WAV::File file(song_info.file_path.c_str()); 701 if (file.hasID3v2Tag()) 702 song_info.tag_type |= T_ID3V2; 703 if (file.hasInfoTag()) 704 song_info.tag_type |= T_RIFF; 705 auto tag = file.tag(); 706 if (tag != nullptr) 707 { 708 TagToSongInfo(song_info, tag, false); 709 } 710 } 711 712 void CTagLibHelper::GetOggTagInfo(SongInfo& song_info) 713 { 714 Vorbis::File file(song_info.file_path.c_str()); 715 auto tag = file.tag(); 716 if (tag != nullptr) 717 { 718 TagToSongInfo(song_info, tag, false); 719 } 720 } 721 722 void CTagLibHelper::GetMpcTagInfo(SongInfo& song_info) 723 { 724 MPC::File file(song_info.file_path.c_str()); 725 if (file.hasAPETag()) 726 song_info.tag_type |= T_APE; 727 if (file.hasID3v1Tag()) 728 song_info.tag_type |= T_ID3V1; 729 auto tag = file.tag(); 730 if (tag != nullptr) 731 { 732 TagToSongInfo(song_info, tag, true); 733 } 734 } 735 736 void CTagLibHelper::GetOpusTagInfo(SongInfo& song_info) 737 { 738 Ogg::Opus::File file(song_info.file_path.c_str()); 739 auto tag = file.tag(); 740 if (tag != nullptr) 741 { 742 TagToSongInfo(song_info, tag, false); 743 } 744 } 745 746 void CTagLibHelper::GetWavPackTagInfo(SongInfo& song_info) 747 { 748 WavPack::File file(song_info.file_path.c_str()); 749 if (file.hasAPETag()) 750 song_info.tag_type |= T_APE; 751 if (file.hasID3v1Tag()) 752 song_info.tag_type |= T_ID3V1; 753 auto tag = file.tag(); 754 if (tag != nullptr) 755 { 756 TagToSongInfo(song_info, tag, true); 757 } 758 } 759 760 void CTagLibHelper::GetTtaTagInfo(SongInfo& song_info) 761 { 762 TrueAudio::File file(song_info.file_path.c_str()); 763 if (file.hasID3v1Tag()) 764 song_info.tag_type |= T_ID3V1; 765 if (file.hasID3v2Tag()) 766 song_info.tag_type |= T_ID3V2; 767 auto tag = file.tag(); 768 if (tag != nullptr) 769 { 770 TagToSongInfo(song_info, tag, true); 771 } 772 } 773 774 void CTagLibHelper::GetAiffTagInfo(SongInfo& song_info) 775 { 776 RIFF::AIFF::File file(song_info.file_path.c_str()); 777 if (file.hasID3v2Tag()) 778 song_info.tag_type |= T_ID3V2; 779 auto tag = file.tag(); 780 if (tag != nullptr) 781 { 782 TagToSongInfo(song_info, tag, false); 783 } 784 } 785 786 void CTagLibHelper::GetSpxTagInfo(SongInfo& song_info) 787 { 788 Ogg::Speex::File file(song_info.file_path.c_str()); 789 auto tag = file.tag(); 790 if (tag != nullptr) 791 { 792 TagToSongInfo(song_info, tag, false); 793 } 794 } 795 796 void CTagLibHelper::GetAnyFileTagInfo(SongInfo& song_info) 797 { 798 FileRef file(song_info.file_path.c_str()); 799 auto tag = file.tag(); 800 if (tag != nullptr) 801 { 802 TagToSongInfo(song_info, tag, false); 803 } 804 } 805 806 void CTagLibHelper::GetFlacPropertyMap(const wstring& file_path, std::map<wstring, wstring>& property_map) 807 { 808 FLAC::File file(file_path.c_str()); 809 if (file.hasXiphComment()) 810 GetTagPropertyMap(file.xiphComment(), property_map); 811 if (file.hasID3v2Tag()) 812 GetTagPropertyMap(file.ID3v2Tag(), property_map); 813 if (file.hasID3v1Tag()) 814 GetTagPropertyMap(file.ID3v1Tag(), property_map); 815 } 816 817 void CTagLibHelper::GetM4aPropertyMap(const wstring& file_path, std::map<wstring, wstring>& property_map) 818 { 819 MP4::File file(file_path.c_str()); 820 auto tag = file.tag(); 821 GetTagPropertyMap(tag, property_map); 822 } 823 824 void CTagLibHelper::GetMpegPropertyMap(const wstring& file_path, std::map<wstring, wstring>& property_map) 825 { 826 MPEG::File file(file_path.c_str()); 827 if (file.hasID3v2Tag()) 828 GetTagPropertyMap(file.ID3v2Tag(), property_map); 829 if (file.hasAPETag()) 830 GetTagPropertyMap(file.APETag(), property_map); 831 if (file.hasID3v1Tag()) 832 GetTagPropertyMap(file.ID3v1Tag(), property_map); 833 } 834 835 void CTagLibHelper::GetAsfPropertyMap(const wstring& file_path, std::map<wstring, wstring>& property_map) 836 { 837 ASF::File file(file_path.c_str()); 838 auto tag = file.tag(); 839 GetTagPropertyMap(tag, property_map); 840 } 841 842 void CTagLibHelper::GetApePropertyMap(const wstring& file_path, std::map<wstring, wstring>& property_map) 843 { 844 APE::File file(file_path.c_str()); 845 if (file.hasAPETag()) 846 GetTagPropertyMap(file.APETag(), property_map); 847 if (file.hasID3v1Tag()) 848 GetTagPropertyMap(file.ID3v1Tag(), property_map); 849 } 850 851 void CTagLibHelper::GetWavPropertyMap(const wstring& file_path, std::map<wstring, wstring>& property_map) 852 { 853 RIFF::WAV::File file(file_path.c_str()); 854 auto tag = file.tag(); 855 GetTagPropertyMap(tag, property_map); 856 } 857 858 void CTagLibHelper::GetOggPropertyMap(const wstring& file_path, std::map<wstring, wstring>& property_map) 859 { 860 Vorbis::File file(file_path.c_str()); 861 auto tag = file.tag(); 862 GetTagPropertyMap(tag, property_map); 863 } 864 865 void CTagLibHelper::GetMpcPropertyMap(const wstring& file_path, std::map<wstring, wstring>& property_map) 866 { 867 MPC::File file(file_path.c_str()); 868 if (file.hasAPETag()) 869 GetTagPropertyMap(file.APETag(), property_map); 870 if (file.hasID3v1Tag()) 871 GetTagPropertyMap(file.ID3v1Tag(), property_map); 872 } 873 874 void CTagLibHelper::GetOpusPropertyMap(const wstring& file_path, std::map<wstring, wstring>& property_map) 875 { 876 Ogg::Opus::File file(file_path.c_str()); 877 auto tag = file.tag(); 878 GetTagPropertyMap(tag, property_map); 879 } 880 881 void CTagLibHelper::GetWavPackPropertyMap(const wstring& file_path, std::map<wstring, wstring>& property_map) 882 { 883 WavPack::File file(file_path.c_str()); 884 if (file.hasAPETag()) 885 GetTagPropertyMap(file.APETag(), property_map); 886 if (file.hasID3v1Tag()) 887 GetTagPropertyMap(file.ID3v1Tag(), property_map); 888 } 889 890 void CTagLibHelper::GetTtaPropertyMap(const wstring& file_path, std::map<wstring, wstring>& property_map) 891 { 892 TrueAudio::File file(file_path.c_str()); 893 if (file.hasID3v2Tag()) 894 GetTagPropertyMap(file.ID3v2Tag(), property_map); 895 if (file.hasID3v1Tag()) 896 GetTagPropertyMap(file.ID3v1Tag(), property_map); 897 } 898 899 void CTagLibHelper::GetAiffPropertyMap(const wstring& file_path, std::map<wstring, wstring>& property_map) 900 { 901 RIFF::AIFF::File file(file_path.c_str()); 902 auto tag = file.tag(); 903 GetTagPropertyMap(tag, property_map); 904 } 905 906 void CTagLibHelper::GetSpxPropertyMap(const wstring& file_path, std::map<wstring, wstring>& property_map) 907 { 908 Ogg::Speex::File file(file_path.c_str()); 909 auto tag = file.tag(); 910 GetTagPropertyMap(tag, property_map); 911 } 912 913 void CTagLibHelper::GetAnyFilePropertyMap(const wstring& file_path, std::map<wstring, wstring>& property_map) 914 { 915 FileRef file(file_path.c_str()); 916 auto tag = file.tag(); 917 GetTagPropertyMap(tag, property_map); 918 } 919 920 wstring CTagLibHelper::GetMpegLyric(const wstring& file_path) 921 { 922 MPEG::File file(file_path.c_str()); 923 auto id3v2 = file.ID3v2Tag(); 924 return GetId3v2Lyric(id3v2); 925 } 926 927 wstring CTagLibHelper::GetM4aLyric(const wstring& file_path) 928 { 929 wstring lyrics; 930 MP4::File file(file_path.c_str()); 931 auto tag = file.tag(); 932 if (tag != nullptr) 933 { 934 auto item_map = file.tag()->itemMap(); 935 auto lyric_item = item_map[STR_MP4_LYRICS_TAG].toStringList();; 936 if (!lyric_item.isEmpty()) 937 lyrics = lyric_item.front().toWString(); 938 } 939 return lyrics; 940 } 941 942 wstring CTagLibHelper::GetFlacLyric(const wstring& file_path) 943 { 944 wstring lyrics; 945 FLAC::File file(file_path.c_str()); 946 auto properties = file.properties(); 947 if (file.isValid()) 948 { 949 auto lyric_item = properties[STR_FLAC_LYRIC_TAG]; 950 if (!lyric_item.isEmpty()) 951 { 952 lyrics = lyric_item.front().toWString(); 953 } 954 } 955 return lyrics; 956 } 957 958 wstring CTagLibHelper::GetAsfLyric(const wstring& file_path) 959 { 960 wstring lyrics; 961 ASF::File file(file_path.c_str()); 962 if (file.isValid()) 963 { 964 auto properties = file.properties(); 965 auto lyric_item = properties[STR_ASF_LYRIC_TAG]; 966 if (!lyric_item.isEmpty()) 967 { 968 lyrics = lyric_item.front().toWString(); 969 } 970 } 971 return lyrics; 972 } 973 974 975 wstring CTagLibHelper::GetWavLyric(const wstring& file_path) 976 { 977 RIFF::WAV::File file(file_path.c_str()); 978 auto id3v2 = file.ID3v2Tag(); 979 return GetId3v2Lyric(id3v2); 980 981 } 982 983 bool CTagLibHelper::WriteMpegLyric(const wstring& file_path, const wstring& lyric_contents) 984 { 985 wstring lyrics; 986 MPEG::File file(file_path.c_str()); 987 auto id3v2 = file.ID3v2Tag(); 988 WriteId3v2Lyric(id3v2, lyric_contents); 989 int tags = MPEG::File::ID3v2; 990 if (file.hasAPETag()) 991 tags |= MPEG::File::APE; 992 bool saved = file.save(tags); 993 return saved; 994 } 995 996 bool CTagLibHelper::WriteFlacLyric(const wstring& file_path, const wstring& lyric_contents) 997 { 998 FLAC::File file(file_path.c_str()); 999 if (file.isValid()) 1000 { 1001 auto properties = file.properties(); 1002 if (lyric_contents.empty()) 1003 { 1004 properties.erase(STR_FLAC_LYRIC_TAG); 1005 } 1006 else 1007 { 1008 StringList lyric_item; 1009 lyric_item.append(lyric_contents); 1010 properties[STR_FLAC_LYRIC_TAG] = lyric_item; 1011 } 1012 file.setProperties(properties); 1013 bool saved = file.save(); 1014 return saved; 1015 } 1016 return false; 1017 } 1018 1019 bool CTagLibHelper::WriteM4aLyric(const wstring& file_path, const wstring& lyric_contents) 1020 { 1021 MP4::File file(file_path.c_str()); 1022 auto tag = file.tag(); 1023 if (tag != nullptr) 1024 { 1025 if (lyric_contents.empty()) 1026 { 1027 tag->removeItem(STR_MP4_LYRICS_TAG); 1028 } 1029 else 1030 { 1031 StringList lyric_list; 1032 lyric_list.append(lyric_contents); 1033 MP4::Item lyrics_item(lyric_list); 1034 tag->setItem(STR_MP4_LYRICS_TAG, lyrics_item); 1035 } 1036 bool saved = file.save(); 1037 return saved; 1038 } 1039 return false; 1040 } 1041 1042 bool CTagLibHelper::WriteAsfLyric(const wstring& file_path, const wstring& lyric_contents) 1043 { 1044 ASF::File file(file_path.c_str()); 1045 if (file.isValid()) 1046 { 1047 auto properties = file.properties(); 1048 if (lyric_contents.empty()) 1049 { 1050 properties.erase(STR_ASF_LYRIC_TAG); 1051 } 1052 else 1053 { 1054 StringList lyric_item; 1055 lyric_item.append(lyric_contents); 1056 properties[STR_ASF_LYRIC_TAG] = lyric_item; 1057 } 1058 file.setProperties(properties); 1059 bool saved = file.save(); 1060 return saved; 1061 } 1062 return false; 1063 } 1064 1065 bool CTagLibHelper::WriteWavLyric(const wstring& file_path, const wstring& lyric_contents) 1066 { 1067 wstring lyrics; 1068 RIFF::WAV::File file(file_path.c_str()); 1069 auto id3v2 = file.ID3v2Tag(); 1070 WriteId3v2Lyric(id3v2, lyric_contents); 1071 bool saved = file.save(); 1072 return saved; 1073 } 1074 1075 bool CTagLibHelper::WriteMp3AlbumCover(const wstring& file_path, const wstring& album_cover_path, bool remove_exist) 1076 { 1077 MPEG::File file(file_path.c_str()); 1078 if (!file.isValid()) 1079 return false; 1080 1081 //先删除专辑封面 1082 if (remove_exist) 1083 { 1084 auto id3v2tag = file.ID3v2Tag(); 1085 DeleteId3v2AlbumCover(id3v2tag); 1086 } 1087 if (!album_cover_path.empty()) 1088 { 1089 auto id3v2tag = file.ID3v2Tag(true); 1090 WriteId3v2AlbumCover(id3v2tag, album_cover_path); 1091 } 1092 int tags = MPEG::File::ID3v2; 1093 if (file.hasAPETag()) 1094 tags |= MPEG::File::APE; 1095 bool saved = file.save(tags); 1096 return saved; 1097 } 1098 1099 bool CTagLibHelper::WriteFlacAlbumCover(const wstring& file_path, const wstring& album_cover_path, bool remove_exist) 1100 { 1101 FLAC::File file(file_path.c_str()); 1102 if (!file.isValid()) 1103 return false; 1104 1105 //先删除专辑封面 1106 if (remove_exist) 1107 { 1108 file.removePictures(); 1109 } 1110 1111 if (!album_cover_path.empty()) 1112 { 1113 ByteVector pic_data; 1114 FileToByteVector(pic_data, album_cover_path); 1115 FLAC::Picture* newpic = new FLAC::Picture(); 1116 newpic->setType(FLAC::Picture::FrontCover); 1117 newpic->setData(pic_data); 1118 wstring ext = CFilePathHelper(album_cover_path).GetFileExtension(); 1119 newpic->setMimeType(L"image/" + ext); 1120 file.addPicture(newpic); 1121 } 1122 bool saved = file.save(); 1123 return saved; 1124 } 1125 1126 bool CTagLibHelper::WriteM4aAlbumCover(const wstring& file_path, const wstring& album_cover_path, bool remove_exist /*= true*/) 1127 { 1128 MP4::File file(file_path.c_str()); 1129 if (!file.isValid()) 1130 return false; 1131 1132 auto tag = file.tag(); 1133 if (tag == nullptr) 1134 return false; 1135 1136 if (remove_exist) 1137 { 1138 if (tag->contains(STR_MP4_COVER_TAG)) 1139 { 1140 tag->removeItem(STR_MP4_COVER_TAG); 1141 } 1142 } 1143 1144 if (!album_cover_path.empty()) 1145 { 1146 ByteVector pic_data; 1147 FileToByteVector(pic_data, album_cover_path); 1148 MP4::CoverArt::Format format = MP4::CoverArt::Format::Unknown; 1149 wstring ext = CFilePathHelper(album_cover_path).GetFileExtension(); 1150 if (ext == L"jpg" || ext == L"jpeg") 1151 format = MP4::CoverArt::Format::JPEG; 1152 else if (ext == L"png") 1153 format = MP4::CoverArt::Format::PNG; 1154 else if (ext == L"gif") 1155 format = MP4::CoverArt::Format::GIF; 1156 else if (ext == L"bmp") 1157 format = MP4::CoverArt::Format::BMP; 1158 MP4::CoverArt cover_item(format, pic_data); 1159 1160 auto cover_item_list = tag->item(STR_MP4_COVER_TAG).toCoverArtList(); 1161 cover_item_list.append(cover_item); 1162 tag->setItem(STR_MP4_COVER_TAG, cover_item_list); 1163 } 1164 bool saved = file.save(); 1165 return saved; 1166 } 1167 1168 bool CTagLibHelper::WriteAsfAlbumCover(const wstring& file_path, const wstring& album_cover_path, bool remove_exist /*= true*/) 1169 { 1170 ASF::File file(file_path.c_str()); 1171 if (!file.isValid()) 1172 return false; 1173 1174 auto tag = file.tag(); 1175 if (tag == nullptr) 1176 return false; 1177 1178 if (remove_exist) 1179 { 1180 if (tag->contains(STR_ASF_COVER_TAG)) 1181 { 1182 tag->removeItem(STR_ASF_COVER_TAG); 1183 } 1184 } 1185 1186 if (!album_cover_path.empty()) 1187 { 1188 ByteVector pic_data; 1189 FileToByteVector(pic_data, album_cover_path); 1190 1191 ASF::Picture picture; 1192 wstring str_mine_type = L"image/" + CFilePathHelper(album_cover_path).GetFileExtension(); 1193 picture.setMimeType(str_mine_type); 1194 picture.setType(ASF::Picture::FrontCover); 1195 picture.setPicture(pic_data); 1196 tag->setAttribute(STR_ASF_COVER_TAG, picture); 1197 } 1198 bool saved = file.save(); 1199 return saved; 1200 } 1201 1202 bool CTagLibHelper::WriteWavAlbumCover(const wstring& file_path, const wstring& album_cover_path, bool remove_exist /*= true*/) 1203 { 1204 RIFF::WAV::File file(file_path.c_str()); 1205 if (!file.isValid()) 1206 return false; 1207 1208 //先删除专辑封面 1209 auto id3v2tag = file.ID3v2Tag(); 1210 if (remove_exist) 1211 { 1212 DeleteId3v2AlbumCover(id3v2tag); 1213 } 1214 if (!album_cover_path.empty()) 1215 { 1216 WriteId3v2AlbumCover(id3v2tag, album_cover_path); 1217 } 1218 bool saved = file.save(); 1219 return saved; 1220 } 1221 1222 bool CTagLibHelper::WriteTtaAlbumCover(const wstring& file_path, const wstring& album_cover_path, bool remove_exist /*= true*/) 1223 { 1224 TrueAudio::File file(file_path.c_str()); 1225 if (!file.isValid()) 1226 return false; 1227 1228 if (remove_exist) 1229 { 1230 auto id3v2tag = file.ID3v2Tag(); 1231 DeleteId3v2AlbumCover(id3v2tag); 1232 } 1233 if (!album_cover_path.empty()) 1234 { 1235 auto id3v2tag = file.ID3v2Tag(true); 1236 WriteId3v2AlbumCover(id3v2tag, album_cover_path); 1237 } 1238 bool saved = file.save(); 1239 return saved; 1240 return false; 1241 } 1242 1243 bool CTagLibHelper::WriteApeAlbumCover(const wstring& file_path, const wstring& album_cover_path, bool remove_exist /*= true*/) 1244 { 1245 APE::File file(file_path.c_str()); 1246 if (!file.isValid()) 1247 return false; 1248 1249 auto tag = file.APETag(true); 1250 WriteApeTagAlbumCover(tag, album_cover_path, remove_exist); 1251 bool saved = file.save(); 1252 return saved; 1253 } 1254 1255 bool CTagLibHelper::WriteOggAlbumCover(const wstring& file_path, const wstring& album_cover_path, bool remove_exist /*= true*/) 1256 { 1257 Ogg::Vorbis::File file(file_path.c_str()); 1258 if (!file.isValid()) 1259 return false; 1260 1261 auto tag = file.tag(); 1262 if (tag != nullptr) 1263 { 1264 WriteXiphCommentAlbumCover(tag, album_cover_path, remove_exist); 1265 bool saved = file.save(); 1266 return saved; 1267 } 1268 return false; 1269 } 1270 1271 bool CTagLibHelper::WriteOpusAlbumCover(const wstring& file_path, const wstring& album_cover_path, bool remove_exist) 1272 { 1273 Ogg::Opus::File file(file_path.c_str()); 1274 if (!file.isValid()) 1275 return false; 1276 1277 auto tag = file.tag(); 1278 if (tag != nullptr) 1279 { 1280 WriteXiphCommentAlbumCover(tag, album_cover_path, remove_exist); 1281 bool saved = file.save(); 1282 return saved; 1283 } 1284 return false; 1285 } 1286 1287 bool CTagLibHelper::WriteSpxAlbumCover(const wstring& file_path, const wstring& album_cover_path, bool remove_exist /*= true*/) 1288 { 1289 Ogg::Speex::File file(file_path.c_str()); 1290 if (!file.isValid()) 1291 return false; 1292 1293 auto tag = file.tag(); 1294 if (tag != nullptr) 1295 { 1296 WriteXiphCommentAlbumCover(tag, album_cover_path, remove_exist); 1297 bool saved = file.save(); 1298 return saved; 1299 } 1300 return false; 1301 } 1302 1303 bool CTagLibHelper::WriteAiffAlbumCover(const wstring& file_path, const wstring& album_cover_path, bool remove_exist /*= true*/) 1304 { 1305 RIFF::AIFF::File file(file_path.c_str()); 1306 if (!file.isValid()) 1307 return false; 1308 1309 //先删除专辑封面 1310 auto id3v2tag = file.tag(); 1311 if (remove_exist) 1312 { 1313 DeleteId3v2AlbumCover(id3v2tag); 1314 } 1315 if (!album_cover_path.empty()) 1316 { 1317 WriteId3v2AlbumCover(id3v2tag, album_cover_path); 1318 } 1319 bool saved = file.save(); 1320 return saved; 1321 } 1322 1323 bool CTagLibHelper::WriteMpcAlbumCover(const wstring& file_path, const wstring& album_cover_path, bool remove_exist /*= true*/) 1324 { 1325 MPC::File file(file_path.c_str()); 1326 if (!file.isValid()) 1327 return false; 1328 1329 auto tag = file.APETag(true); 1330 WriteApeTagAlbumCover(tag, album_cover_path, remove_exist); 1331 bool saved = file.save(); 1332 return saved; 1333 } 1334 1335 bool CTagLibHelper::WriteWavePackAlbumCover(const wstring& file_path, const wstring& album_cover_path, bool remove_exist /*= true*/) 1336 { 1337 WavPack::File file(file_path.c_str()); 1338 if (!file.isValid()) 1339 return false; 1340 1341 auto tag = file.APETag(true); 1342 WriteApeTagAlbumCover(tag, album_cover_path, remove_exist); 1343 bool saved = file.save(); 1344 return saved; 1345 } 1346 1347 bool CTagLibHelper::WriteMpegTag(SongInfo& song_info) 1348 { 1349 MPEG::File file(song_info.file_path.c_str()); 1350 auto tag = file.tag(); 1351 SongInfoToTag(song_info, tag); 1352 int tags = MPEG::File::ID3v2; 1353 //if (file.hasID3v1Tag()) 1354 // tags |= MPEG::File::ID3v1; 1355 if (file.hasAPETag()) 1356 tags |= MPEG::File::APE; 1357 bool saved = file.save(tags); 1358 return saved; 1359 } 1360 1361 bool CTagLibHelper::WriteFlacTag(SongInfo& song_info) 1362 { 1363 FLAC::File file(song_info.file_path.c_str()); 1364 auto tag = file.tag(); 1365 SongInfoToTag(song_info, tag); 1366 bool saved = file.save(); 1367 return saved; 1368 } 1369 1370 bool CTagLibHelper::WriteM4aTag(SongInfo& song_info) 1371 { 1372 MP4::File file(song_info.file_path.c_str()); 1373 auto tag = file.tag(); 1374 SongInfoToTag(song_info, tag); 1375 bool saved = file.save(); 1376 return saved; 1377 } 1378 1379 bool CTagLibHelper::WriteWavTag(SongInfo& song_info) 1380 { 1381 RIFF::WAV::File file(song_info.file_path.c_str()); 1382 auto tag = file.tag(); 1383 SongInfoToTag(song_info, tag); 1384 bool saved = file.save(); 1385 return saved; 1386 } 1387 1388 bool CTagLibHelper::WriteOggTag(SongInfo& song_info) 1389 { 1390 Vorbis::File file(song_info.file_path.c_str()); 1391 auto tag = file.tag(); 1392 SongInfoToTag(song_info, tag); 1393 bool saved = file.save(); 1394 return saved; 1395 } 1396 1397 bool CTagLibHelper::WriteApeTag(SongInfo& song_info) 1398 { 1399 APE::File file(song_info.file_path.c_str()); 1400 auto tag = file.tag(); 1401 SongInfoToTag(song_info, tag); 1402 bool saved = file.save(); 1403 return saved; 1404 } 1405 1406 bool CTagLibHelper::WriteMpcTag(SongInfo& song_info) 1407 { 1408 MPC::File file(song_info.file_path.c_str()); 1409 auto tag = file.tag(); 1410 SongInfoToTag(song_info, tag); 1411 bool saved = file.save(); 1412 return saved; 1413 } 1414 1415 bool CTagLibHelper::WriteOpusTag(SongInfo& song_info) 1416 { 1417 Ogg::Opus::File file(song_info.file_path.c_str()); 1418 auto tag = file.tag(); 1419 SongInfoToTag(song_info, tag); 1420 bool saved = file.save(); 1421 return saved; 1422 } 1423 1424 bool CTagLibHelper::WriteWavPackTag(SongInfo& song_info) 1425 { 1426 WavPack::File file(song_info.file_path.c_str()); 1427 auto tag = file.tag(); 1428 SongInfoToTag(song_info, tag); 1429 bool saved = file.save(); 1430 return saved; 1431 } 1432 1433 bool CTagLibHelper::WriteTtaTag(SongInfo& song_info) 1434 { 1435 TrueAudio::File file(song_info.file_path.c_str()); 1436 auto tag = file.tag(); 1437 SongInfoToTag(song_info, tag); 1438 bool saved = file.save(); 1439 return saved; 1440 } 1441 1442 bool CTagLibHelper::WriteAiffTag(SongInfo& song_info) 1443 { 1444 RIFF::AIFF::File file(song_info.file_path.c_str()); 1445 auto tag = file.tag(); 1446 SongInfoToTag(song_info, tag); 1447 bool saved = file.save(); 1448 return saved; 1449 } 1450 1451 bool CTagLibHelper::WriteAsfTag(SongInfo& song_info) 1452 { 1453 ASF::File file(song_info.file_path.c_str()); 1454 auto tag = file.tag(); 1455 SongInfoToTag(song_info, tag); 1456 bool saved = file.save(); 1457 return saved; 1458 } 1459 1460 bool CTagLibHelper::WriteSpxTag(SongInfo& song_info) 1461 { 1462 Ogg::Speex::File file(song_info.file_path.c_str()); 1463 auto tag = file.tag(); 1464 SongInfoToTag(song_info, tag); 1465 bool saved = file.save(); 1466 return saved; 1467 } 1468 1469 wstring CTagLibHelper::GetApeCue(const wstring& file_path) 1470 { 1471 wstring cue_contents; 1472 APE::File file(file_path.c_str()); 1473 auto tag = file.APETag(); 1474 if (tag != nullptr) 1475 { 1476 auto item_list_map = tag->itemListMap(); 1477 auto cue_item = item_list_map[STR_APE_CUE_TAG]; 1478 cue_contents = cue_item.toString().toWString(); 1479 } 1480 return cue_contents; 1481 } 1482 1483 int CTagLibHelper::GetMepgRating(const wstring& file_path) 1484 { 1485 MPEG::File file(file_path.c_str()); 1486 auto id3v2 = file.ID3v2Tag(); 1487 return GetId3v2Rating(id3v2); 1488 } 1489 1490 bool CTagLibHelper::WriteMpegRating(const wstring& file_path, int rate) 1491 { 1492 MPEG::File file(file_path.c_str()); 1493 auto id3v2 = file.ID3v2Tag(); 1494 WriteId3v2Rating(id3v2, rate); 1495 int tags = MPEG::File::ID3v2; 1496 if (file.hasAPETag()) 1497 tags |= MPEG::File::APE; 1498 bool saved = file.save(tags); 1499 return saved; 1500 } 1501