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/apefile.h" 13 #include "taglib/wavfile.h" 14 #include "taglib/mpcfile.h" 15 #include "taglib/opusfile.h" 16 #include "taglib/wavpackfile.h" 17 #include "taglib/vorbisfile.h" 18 #include "taglib/trueaudiofile.h" 19 #include "taglib/aifffile.h" 20 #include "taglib/asffile.h" 21 #include "taglib/tpropertymap.h" 22 #include "AudioCommon.h" 23 #include "taglib/apetag.h" 24 #include "taglib/fileref.h" 25 #include "taglib/speexfile.h" 26 27 28 using namespace TagLib; 29 30 #define STR_MP4_COVER_TAG "covr" 31 #define STR_MP4_LYRICS_TAG "----:com.apple.iTunes:Lyrics" 32 #define STR_ASF_COVER_TAG "WM/Picture" 33 #define STR_APE_COVER_TAG "COVER ART (FRONT)" 34 35 //��taglib�е��ַ���ת����wstring���͡� 36 //����taglib�����з�unicode����ȫ����ΪLatin���봦���������ȷ�����ش���ҳ 37 //���ォLatin������ַ��������ش���ҳ���� 38 static wstring TagStringToWstring(const String& str, bool to_local) 39 { 40 wstring result; 41 if (to_local && str.isLatin1()) 42 result = CCommon::StrToUnicode(str.to8Bit(), CodeType::ANSI); 43 else 44 result = str.toWString(); 45 return result; 46 } 47 48 static void SongInfoToTag(const SongInfo& song_info, Tag* tag) 49 { 50 if (tag != nullptr) 51 { 52 tag->setTitle(song_info.title); 53 tag->setArtist(song_info.artist); 54 tag->setAlbum(song_info.album); 55 tag->setGenre(song_info.genre); 56 tag->setTrack(song_info.track); 57 tag->setComment(song_info.comment); 58 tag->setYear(song_info.year); 59 } 60 } 61 62 static bool IsStringNumber(wstring str, int num) 63 { 64 if (!str.empty() && str.front() == L'(') 65 str = str.substr(1); 66 if (!str.empty() && str.back() == L')') 67 str.pop_back(); 68 if (CCommon::StrIsNumber(str)) 69 { 70 num = _wtoi(str.c_str()); 71 return true; 72 } 73 return false; 74 } 75 76 static void TagToSongInfo(SongInfo& song_info, Tag* tag, bool to_local) 77 { 78 if (tag != nullptr) 79 { 80 song_info.title = TagStringToWstring(tag->title(), to_local); 81 song_info.artist = TagStringToWstring(tag->artist(), to_local); 82 song_info.album = TagStringToWstring(tag->album(), to_local); 83 song_info.genre = TagStringToWstring(tag->genre(), to_local); 84 int genre_num{}; 85 if (IsStringNumber(song_info.genre, genre_num)) 86 { 87 song_info.genre = CAudioCommon::GetGenre(static_cast<BYTE>(genre_num)); 88 } 89 90 song_info.year = tag->year(); 91 song_info.track = tag->track(); 92 song_info.comment = TagStringToWstring(tag->comment(), to_local); 93 } 94 } 95 96 //���ļ����ݶ�ȡ��ByteVector 97 static void FileToByteVector(ByteVector& data, const std::wstring& file_path) 98 { 99 std::ifstream file{ file_path, std::ios::binary | std::ios::in }; 100 if (file.fail()) 101 return; 102 103 //��ȡ�ļ����� 104 file.seekg(0, file.end); 105 size_t length = file.tellg(); 106 file.seekg(0, file.beg); 107 108 data.clear(); 109 data.resize(static_cast<unsigned int>(length)); 110 111 file.read(data.data(), length); 112 113 file.close(); 114 } 115 116 int GetPicType(const wstring& mimeType) 117 { 118 int type{ -1 }; 119 if (mimeType == L"image/jpeg" || mimeType == L"image/jpg") 120 type = 0; 121 else if (mimeType == L"image/png") 122 type = 1; 123 else if (mimeType == L"image/gif") 124 type = 2; 125 else if (mimeType == L"image/bmp") 126 type = 3; 127 else 128 type = -1; 129 return type; 130 } 131 132 static void GetId3v2AlbumCover(ID3v2::Tag* id3v2, string& cover_contents, int& type) 133 { 134 if (id3v2 != nullptr) 135 { 136 auto pic_frame_list = id3v2->frameListMap()["APIC"]; 137 if (!pic_frame_list.isEmpty()) 138 { 139 ID3v2::AttachedPictureFrame *frame = dynamic_cast<TagLib::ID3v2::AttachedPictureFrame*>(pic_frame_list.front()); 140 if (frame != nullptr) 141 { 142 auto pic_data = frame->picture(); 143 //��ȡר������ 144 cover_contents.assign(pic_data.data(), pic_data.size()); 145 wstring img_type = frame->mimeType().toCWString(); 146 type = GetPicType(img_type); 147 } 148 } 149 } 150 } 151 152 static void DeleteId3v2AlbumCover(ID3v2::Tag* id3v2tag) 153 { 154 if (id3v2tag != nullptr) 155 { 156 auto pic_frame_list = id3v2tag->frameListMap()["APIC"]; 157 if (!pic_frame_list.isEmpty()) 158 { 159 for (auto frame : pic_frame_list) 160 id3v2tag->removeFrame(frame); 161 } 162 } 163 } 164 165 static void WriteId3v2AlbumCover(ID3v2::Tag* id3v2tag, const wstring& album_cover_path) 166 { 167 if (id3v2tag != nullptr) 168 { 169 //��ȡͼƬ�ļ� 170 ByteVector pic_data; 171 FileToByteVector(pic_data, album_cover_path); 172 //����Ƶ�ļ�д��ͼƬ�ļ� 173 ID3v2::AttachedPictureFrame* pic_frame = new ID3v2::AttachedPictureFrame(); 174 pic_frame->setPicture(pic_data); 175 pic_frame->setType(ID3v2::AttachedPictureFrame::FrontCover); 176 wstring ext = CFilePathHelper(album_cover_path).GetFileExtension(); 177 pic_frame->setMimeType(L"image/" + ext); 178 id3v2tag->addFrame(pic_frame); 179 } 180 } 181 182 183 static void GetApeTagAlbumCover(APE::Tag* tag, string& cover_contents, int& type) 184 { 185 if (tag != nullptr) 186 { 187 auto item_list_map = tag->itemListMap(); 188 auto pic_item = item_list_map[STR_APE_COVER_TAG]; 189 auto pic_data = pic_item.binaryData(); 190 if (!pic_data.isEmpty()) 191 { 192 cover_contents.assign(pic_data.data(), pic_data.size()); 193 194 size_t index{}; 195 index = cover_contents.find('\0'); 196 std::string pic_desc; 197 if (index != std::string::npos) 198 { 199 pic_desc = cover_contents.substr(0, index); 200 cover_contents = cover_contents.substr(index + 1); 201 } 202 203 if (!pic_desc.empty()) 204 { 205 std::string img_type; 206 index = pic_desc.rfind('.'); 207 if (index != std::string::npos && index < pic_desc.size() - 1) 208 { 209 img_type = pic_desc.substr(index + 1); 210 img_type = "image/" + img_type; 211 type = GetPicType(CCommon::ASCIIToUnicode(img_type)); 212 } 213 } 214 } 215 } 216 } 217 218 static void WriteApeTagAlbumCover(APE::Tag* tag, const wstring &album_cover_path, bool remove_exist) 219 { 220 if (remove_exist) 221 { 222 tag->removeItem(STR_APE_COVER_TAG); 223 } 224 225 if (!album_cover_path.empty()) 226 { 227 ByteVector pic_data; 228 FileToByteVector(pic_data, album_cover_path); 229 230 ByteVector pic_item_data; 231 pic_item_data = "Cover Art (Front)."; 232 wstring file_type = CFilePathHelper(album_cover_path).GetFileExtension(); 233 for (wchar_t ch : file_type) 234 pic_item_data.append(static_cast<char>(ch)); 235 pic_item_data.append('\0'); 236 pic_item_data.append(pic_data); 237 238 APE::Item pic_item(STR_APE_COVER_TAG, pic_item_data, true); 239 tag->setItem(STR_APE_COVER_TAG, pic_item); 240 } 241 } 242 243 static void WriteXiphCommentAlbumCover(Ogg::XiphComment * tag, const wstring &album_cover_path, bool remove_exist) 244 { 245 //��ɾ��ר������ 246 if (remove_exist) 247 { 248 tag->removeAllPictures(); 249 } 250 251 if (!album_cover_path.empty()) 252 { 253 ByteVector pic_data; 254 FileToByteVector(pic_data, album_cover_path); 255 FLAC::Picture *newpic = new FLAC::Picture(); 256 newpic->setType(FLAC::Picture::FrontCover); 257 newpic->setData(pic_data); 258 wstring ext = CFilePathHelper(album_cover_path).GetFileExtension(); 259 newpic->setMimeType(L"image/" + ext); 260 tag->addPicture(newpic); 261 } 262 } 263 264 265 void GetXiphCommentAlbumCover(Ogg::XiphComment * tag, string &cover_contents, int& type) 266 { 267 const auto& cover_list = tag->pictureList(); 268 if (!cover_list.isEmpty()) 269 { 270 auto pic = cover_list.front(); 271 if (pic != nullptr) 272 { 273 const auto& pic_data = pic->data(); 274 //��ȡר������ 275 cover_contents.assign(pic_data.data(), pic_data.size()); 276 277 wstring img_type = pic->mimeType().toCWString(); 278 type = GetPicType(img_type); 279 } 280 } 281 } 282 283 284 /////////////////////////////////////////////////////////////////////////////////// 285 /////////////////////////////////////////////////////////////////////////////////// 286 287 CTagLibHelper::CTagLibHelper() 288 { 289 } 290 291 CTagLibHelper::~CTagLibHelper() 292 { 293 } 294 295 string CTagLibHelper::GetM4aAlbumCover(const wstring& file_path, int& type) 296 { 297 string cover_contents; 298 MP4::File file(file_path.c_str()); 299 auto tag = file.tag(); 300 if(tag != nullptr) 301 { 302 auto cover_item = tag->item(STR_MP4_COVER_TAG).toCoverArtList(); 303 if (!cover_item.isEmpty()) 304 { 305 const auto& pic_data = cover_item.front().data(); 306 //��ȡר������ 307 cover_contents.assign(pic_data.data(), pic_data.size()); 308 309 //��ȡ�����ʽ 310 switch (cover_item.front().format()) 311 { 312 case MP4::CoverArt::JPEG: 313 type = 0; 314 break; 315 case MP4::CoverArt::PNG: 316 type = 1; 317 break; 318 case MP4::CoverArt::BMP: 319 type = 3; 320 break; 321 case MP4::CoverArt::GIF: 322 type = 2; 323 break; 324 default: 325 type = -1; 326 break; 327 } 328 } 329 } 330 return cover_contents; 331 } 332 333 string CTagLibHelper::GetFlacAlbumCover(const wstring& file_path, int& type) 334 { 335 string cover_contents; 336 FLAC::File file(file_path.c_str()); 337 const auto& cover_list = file.pictureList(); 338 if (!cover_list.isEmpty()) 339 { 340 auto pic = cover_list.front(); 341 if (pic != nullptr) 342 { 343 const auto& pic_data = pic->data(); 344 //��ȡר������ 345 cover_contents.assign(pic_data.data(), pic_data.size()); 346 347 wstring img_type = pic->mimeType().toCWString(); 348 type = GetPicType(img_type); 349 } 350 } 351 return cover_contents; 352 } 353 354 string CTagLibHelper::GetMp3AlbumCover(const wstring & file_path, int & type) 355 { 356 string cover_contents; 357 MPEG::File file(file_path.c_str()); 358 auto id3v2 = file.ID3v2Tag(); 359 GetId3v2AlbumCover(id3v2, cover_contents, type); 360 return cover_contents; 361 } 362 363 string CTagLibHelper::GetAsfAlbumCover(const wstring& file_path, int& type) 364 { 365 string cover_contents; 366 ASF::File file(file_path.c_str()); 367 auto tag = file.tag(); 368 if (tag != nullptr) 369 { 370 ASF::AttributeList attr = tag->attribute("WM/Picture"); 371 if (!attr.isEmpty()) 372 { 373 ASF::Picture picture = attr.front().toPicture(); 374 auto pic_data = picture.picture(); 375 cover_contents.assign(pic_data.data(), pic_data.size()); 376 wstring img_type = picture.mimeType().toCWString(); 377 type = GetPicType(img_type); 378 } 379 } 380 return cover_contents; 381 } 382 383 string CTagLibHelper::GetWavAlbumCover(const wstring& file_path, int& type) 384 { 385 string cover_contents; 386 RIFF::WAV::File file(file_path.c_str()); 387 auto id3v2 = file.ID3v2Tag(); 388 GetId3v2AlbumCover(id3v2, cover_contents, type); 389 return cover_contents; 390 } 391 392 string CTagLibHelper::GetTtaAlbumCover(const wstring& file_path, int& type) 393 { 394 string cover_contents; 395 TrueAudio::File file(file_path.c_str()); 396 auto id3v2 = file.ID3v2Tag(); 397 GetId3v2AlbumCover(id3v2, cover_contents, type); 398 return cover_contents; 399 } 400 401 string CTagLibHelper::GetApeAlbumCover(const wstring& file_path, int& type) 402 { 403 string cover_contents; 404 APE::File file(file_path.c_str()); 405 auto tag = file.APETag(); 406 GetApeTagAlbumCover(tag, cover_contents, type); 407 return cover_contents; 408 } 409 410 411 string CTagLibHelper::GetOggAlbumCover(const wstring& file_path, int& type) 412 { 413 string cover_contents; 414 Ogg::Vorbis::File file(file_path.c_str()); 415 auto tag = file.tag(); 416 if (tag != nullptr) 417 { 418 GetXiphCommentAlbumCover(tag, cover_contents, type); 419 } 420 return cover_contents; 421 } 422 423 string CTagLibHelper::GetOpusAlbumCover(const wstring & file_path, int & type) 424 { 425 string cover_contents; 426 Ogg::Opus::File file(file_path.c_str()); 427 auto tag = file.tag(); 428 if (tag != nullptr) 429 { 430 GetXiphCommentAlbumCover(tag, cover_contents, type); 431 } 432 return cover_contents; 433 } 434 435 string CTagLibHelper::GetSpxAlbumCover(const wstring& file_path, int& type) 436 { 437 string cover_contents; 438 Ogg::Speex::File file(file_path.c_str()); 439 auto tag = file.tag(); 440 if (tag != nullptr) 441 { 442 GetXiphCommentAlbumCover(tag, cover_contents, type); 443 } 444 return cover_contents; 445 } 446 447 string CTagLibHelper::GetAiffAlbumCover(const wstring& file_path, int& type) 448 { 449 string cover_contents; 450 RIFF::AIFF::File file(file_path.c_str()); 451 auto id3v2 = file.tag(); 452 GetId3v2AlbumCover(id3v2, cover_contents, type); 453 return cover_contents; 454 455 } 456 457 string CTagLibHelper::GetMpcAlbumCover(const wstring& file_path, int& type) 458 { 459 string cover_contents; 460 MPC::File file(file_path.c_str()); 461 auto ape_tag = file.APETag(); 462 GetApeTagAlbumCover(ape_tag, cover_contents, type); 463 return cover_contents; 464 } 465 466 string CTagLibHelper::GetWavePackAlbumCover(const wstring& file_path, int& type) 467 { 468 string cover_contents; 469 WavPack::File file(file_path.c_str()); 470 auto ape_tag = file.APETag(); 471 GetApeTagAlbumCover(ape_tag, cover_contents, type); 472 return cover_contents; 473 } 474 475 void CTagLibHelper::GetFlacTagInfo(SongInfo& song_info) 476 { 477 FLAC::File file(song_info.file_path.c_str()); 478 if (file.hasID3v1Tag()) 479 song_info.tag_type |= T_ID3V1; 480 if (file.hasID3v2Tag()) 481 song_info.tag_type |= T_ID3V2; 482 auto tag = file.tag(); 483 if (tag != nullptr) 484 { 485 TagToSongInfo(song_info, tag, true); 486 } 487 } 488 489 void CTagLibHelper::GetM4aTagInfo(SongInfo& song_info) 490 { 491 MP4::File file(song_info.file_path.c_str()); 492 if (file.hasMP4Tag()) 493 song_info.tag_type |= T_MP4; 494 auto tag = file.tag(); 495 if (tag != nullptr) 496 { 497 TagToSongInfo(song_info, tag, false); 498 } 499 } 500 501 void CTagLibHelper::GetMpegTagInfo(SongInfo& song_info) 502 { 503 MPEG::File file(song_info.file_path.c_str()); 504 if (file.hasID3v1Tag()) 505 song_info.tag_type |= T_ID3V1; 506 if (file.hasID3v2Tag()) 507 song_info.tag_type |= T_ID3V2; 508 if (file.hasAPETag()) 509 song_info.tag_type |= T_APE; 510 511 auto tag = file.tag(); 512 if (tag != nullptr) 513 { 514 TagToSongInfo(song_info, tag, true); 515 } 516 } 517 518 void CTagLibHelper::GetAsfTagInfo(SongInfo& song_info) 519 { 520 ASF::File file(song_info.file_path.c_str()); 521 auto tag = file.tag(); 522 if (tag != nullptr) 523 { 524 TagToSongInfo(song_info, tag, false); 525 } 526 } 527 528 void CTagLibHelper::GetApeTagInfo(SongInfo& song_info) 529 { 530 APE::File file(song_info.file_path.c_str()); 531 if (file.hasID3v1Tag()) 532 song_info.tag_type |= T_ID3V1; 533 if (file.hasAPETag()) 534 song_info.tag_type |= T_APE; 535 536 auto tag = file.tag(); 537 if (tag != nullptr) 538 { 539 TagToSongInfo(song_info, tag, true); 540 } 541 } 542 543 void CTagLibHelper::GetWavTagInfo(SongInfo& song_info) 544 { 545 RIFF::WAV::File file(song_info.file_path.c_str()); 546 if (file.hasID3v2Tag()) 547 song_info.tag_type |= T_ID3V2; 548 if (file.hasInfoTag()) 549 song_info.tag_type |= T_RIFF; 550 auto tag = file.tag(); 551 if (tag != nullptr) 552 { 553 TagToSongInfo(song_info, tag, false); 554 } 555 } 556 557 void CTagLibHelper::GetOggTagInfo(SongInfo& song_info) 558 { 559 Vorbis::File file(song_info.file_path.c_str()); 560 auto tag = file.tag(); 561 if (tag != nullptr) 562 { 563 TagToSongInfo(song_info, tag, false); 564 } 565 } 566 567 void CTagLibHelper::GetMpcTagInfo(SongInfo& song_info) 568 { 569 MPC::File file(song_info.file_path.c_str()); 570 if (file.hasAPETag()) 571 song_info.tag_type |= T_APE; 572 if (file.hasID3v1Tag()) 573 song_info.tag_type |= T_ID3V1; 574 auto tag = file.tag(); 575 if (tag != nullptr) 576 { 577 TagToSongInfo(song_info, tag, true); 578 } 579 } 580 581 void CTagLibHelper::GetOpusTagInfo(SongInfo& song_info) 582 { 583 Ogg::Opus::File file(song_info.file_path.c_str()); 584 auto tag = file.tag(); 585 if (tag != nullptr) 586 { 587 TagToSongInfo(song_info, tag, false); 588 } 589 } 590 591 void CTagLibHelper::GetWavPackTagInfo(SongInfo& song_info) 592 { 593 WavPack::File file(song_info.file_path.c_str()); 594 if (file.hasAPETag()) 595 song_info.tag_type |= T_APE; 596 if (file.hasID3v1Tag()) 597 song_info.tag_type |= T_ID3V1; 598 auto tag = file.tag(); 599 if (tag != nullptr) 600 { 601 TagToSongInfo(song_info, tag, true); 602 } 603 } 604 605 void CTagLibHelper::GetTtaTagInfo(SongInfo& song_info) 606 { 607 TrueAudio::File file(song_info.file_path.c_str()); 608 if (file.hasID3v1Tag()) 609 song_info.tag_type |= T_ID3V1; 610 if (file.hasID3v2Tag()) 611 song_info.tag_type |= T_ID3V2; 612 auto tag = file.tag(); 613 if (tag != nullptr) 614 { 615 TagToSongInfo(song_info, tag, true); 616 } 617 } 618 619 void CTagLibHelper::GetAiffTagInfo(SongInfo& song_info) 620 { 621 RIFF::AIFF::File file(song_info.file_path.c_str()); 622 if (file.hasID3v2Tag()) 623 song_info.tag_type |= T_ID3V2; 624 auto tag = file.tag(); 625 if (tag != nullptr) 626 { 627 TagToSongInfo(song_info, tag, false); 628 } 629 } 630 631 void CTagLibHelper::GetSpxTagInfo(SongInfo& song_info) 632 { 633 Ogg::Speex::File file(song_info.file_path.c_str()); 634 auto tag = file.tag(); 635 if (tag != nullptr) 636 { 637 TagToSongInfo(song_info, tag, false); 638 } 639 } 640 641 void CTagLibHelper::GetAnyFileTagInfo(SongInfo & song_info) 642 { 643 FileRef file(song_info.file_path.c_str()); 644 auto tag = file.tag(); 645 if (tag != nullptr) 646 { 647 TagToSongInfo(song_info, tag, false); 648 } 649 } 650 651 wstring CTagLibHelper::GetMpegLyric(const wstring& file_path) 652 { 653 wstring lyrics; 654 MPEG::File file(file_path.c_str()); 655 auto id3v2 = file.ID3v2Tag(); 656 if (id3v2 != nullptr) 657 { 658 auto frame_list_map = id3v2->frameListMap(); 659 auto lyric_frame = frame_list_map["USLT"]; 660 if (!lyric_frame.isEmpty()) 661 lyrics = lyric_frame.front()->toString().toWString(); 662 } 663 return lyrics; 664 } 665 666 wstring CTagLibHelper::GetM4aLyric(const wstring& file_path) 667 { 668 wstring lyrics; 669 MP4::File file(file_path.c_str()); 670 auto tag = file.tag(); 671 if (tag != nullptr) 672 { 673 auto item_map = file.tag()->itemMap(); 674 auto lyric_item = item_map[STR_MP4_LYRICS_TAG].toStringList();; 675 if (!lyric_item.isEmpty()) 676 lyrics = lyric_item.front().toWString(); 677 } 678 return lyrics; 679 } 680 681 wstring CTagLibHelper::GetFlacLyric(const wstring& file_path) 682 { 683 wstring lyrics; 684 FLAC::File file(file_path.c_str()); 685 auto properties = file.properties(); 686 auto lyric_item = properties["LYRICS"]; 687 if (!lyric_item.isEmpty()) 688 { 689 lyrics = lyric_item.front().toWString(); 690 } 691 return lyrics; 692 } 693 694 wstring CTagLibHelper::GetAsfLyric(const wstring& file_path) 695 { 696 wstring lyrics; 697 ASF::File file(file_path.c_str()); 698 auto properties = file.properties(); 699 auto lyric_item = properties["LYRICS"]; 700 if (!lyric_item.isEmpty()) 701 { 702 lyrics = lyric_item.front().toWString(); 703 } 704 return lyrics; 705 } 706 707 708 bool CTagLibHelper::WriteMp3AlbumCover(const wstring& file_path, const wstring& album_cover_path, bool remove_exist) 709 { 710 MPEG::File file(file_path.c_str()); 711 if (!file.isValid()) 712 return false; 713 714 //��ɾ��ר������ 715 if (remove_exist) 716 { 717 auto id3v2tag = file.ID3v2Tag(); 718 DeleteId3v2AlbumCover(id3v2tag); 719 } 720 if (!album_cover_path.empty()) 721 { 722 auto id3v2tag = file.ID3v2Tag(true); 723 WriteId3v2AlbumCover(id3v2tag, album_cover_path); 724 } 725 bool saved = file.save(MPEG::File::ID3v2); 726 return saved; 727 } 728 729 bool CTagLibHelper::WriteFlacAlbumCover(const wstring& file_path, const wstring& album_cover_path, bool remove_exist) 730 { 731 FLAC::File file(file_path.c_str()); 732 if (!file.isValid()) 733 return false; 734 735 //��ɾ��ר������ 736 if (remove_exist) 737 { 738 file.removePictures(); 739 } 740 741 if (!album_cover_path.empty()) 742 { 743 ByteVector pic_data; 744 FileToByteVector(pic_data, album_cover_path); 745 FLAC::Picture *newpic = new FLAC::Picture(); 746 newpic->setType(FLAC::Picture::FrontCover); 747 newpic->setData(pic_data); 748 wstring ext = CFilePathHelper(album_cover_path).GetFileExtension(); 749 newpic->setMimeType(L"image/" + ext); 750 file.addPicture(newpic); 751 } 752 bool saved = file.save(); 753 return saved; 754 } 755 756 bool CTagLibHelper::WriteM4aAlbumCover(const wstring& file_path, const wstring& album_cover_path, bool remove_exist /*= true*/) 757 { 758 MP4::File file(file_path.c_str()); 759 if (!file.isValid()) 760 return false; 761 762 auto tag = file.tag(); 763 if (tag == nullptr) 764 return false; 765 766 if (remove_exist) 767 { 768 if (tag->contains(STR_MP4_COVER_TAG)) 769 { 770 tag->removeItem(STR_MP4_COVER_TAG); 771 } 772 } 773 774 if (!album_cover_path.empty()) 775 { 776 ByteVector pic_data; 777 FileToByteVector(pic_data, album_cover_path); 778 MP4::CoverArt::Format format = MP4::CoverArt::Format::Unknown; 779 wstring ext = CFilePathHelper(album_cover_path).GetFileExtension(); 780 if (ext == L"jpg" || ext == L"jpeg") 781 format = MP4::CoverArt::Format::JPEG; 782 else if (ext == L"png") 783 format = MP4::CoverArt::Format::PNG; 784 else if (ext == L"gif") 785 format = MP4::CoverArt::Format::GIF; 786 else if (ext == L"bmp") 787 format = MP4::CoverArt::Format::BMP; 788 MP4::CoverArt cover_item(format, pic_data); 789 790 auto cover_item_list = tag->item(STR_MP4_COVER_TAG).toCoverArtList(); 791 cover_item_list.append(cover_item); 792 tag->setItem(STR_MP4_COVER_TAG, cover_item_list); 793 } 794 bool saved = file.save(); 795 return saved; 796 } 797 798 bool CTagLibHelper::WriteAsfAlbumCover(const wstring& file_path, const wstring& album_cover_path, bool remove_exist /*= true*/) 799 { 800 ASF::File file(file_path.c_str()); 801 if (!file.isValid()) 802 return false; 803 804 auto tag = file.tag(); 805 if (tag == nullptr) 806 return false; 807 808 if (remove_exist) 809 { 810 if (tag->contains(STR_ASF_COVER_TAG)) 811 { 812 tag->removeItem(STR_ASF_COVER_TAG); 813 } 814 } 815 816 if (!album_cover_path.empty()) 817 { 818 ByteVector pic_data; 819 FileToByteVector(pic_data, album_cover_path); 820 821 ASF::Picture picture; 822 wstring str_mine_type = L"image/" + CFilePathHelper(album_cover_path).GetFileExtension(); 823 picture.setMimeType(str_mine_type); 824 picture.setType(ASF::Picture::FrontCover); 825 picture.setPicture(pic_data); 826 tag->setAttribute(STR_ASF_COVER_TAG, picture); 827 } 828 bool saved = file.save(); 829 return saved; 830 } 831 832 bool CTagLibHelper::WriteWavAlbumCover(const wstring& file_path, const wstring& album_cover_path, bool remove_exist /*= true*/) 833 { 834 RIFF::WAV::File file(file_path.c_str()); 835 if (!file.isValid()) 836 return false; 837 838 //��ɾ��ר������ 839 auto id3v2tag = file.ID3v2Tag(); 840 if (remove_exist) 841 { 842 DeleteId3v2AlbumCover(id3v2tag); 843 } 844 if (!album_cover_path.empty()) 845 { 846 WriteId3v2AlbumCover(id3v2tag, album_cover_path); 847 } 848 bool saved = file.save(); 849 return saved; 850 } 851 852 bool CTagLibHelper::WriteTtaAlbumCover(const wstring& file_path, const wstring& album_cover_path, bool remove_exist /*= true*/) 853 { 854 TrueAudio::File file(file_path.c_str()); 855 if (!file.isValid()) 856 return false; 857 858 if (remove_exist) 859 { 860 auto id3v2tag = file.ID3v2Tag(); 861 DeleteId3v2AlbumCover(id3v2tag); 862 } 863 if (!album_cover_path.empty()) 864 { 865 auto id3v2tag = file.ID3v2Tag(true); 866 WriteId3v2AlbumCover(id3v2tag, album_cover_path); 867 } 868 bool saved = file.save(); 869 return saved; 870 return false; 871 } 872 873 bool CTagLibHelper::WriteApeAlbumCover(const wstring& file_path, const wstring& album_cover_path, bool remove_exist /*= true*/) 874 { 875 APE::File file(file_path.c_str()); 876 if (!file.isValid()) 877 return false; 878 879 auto tag = file.APETag(true); 880 WriteApeTagAlbumCover(tag, album_cover_path, remove_exist); 881 bool saved = file.save(); 882 return saved; 883 } 884 885 bool CTagLibHelper::WriteOggAlbumCover(const wstring& file_path, const wstring& album_cover_path, bool remove_exist /*= true*/) 886 { 887 Ogg::Vorbis::File file(file_path.c_str()); 888 if (!file.isValid()) 889 return false; 890 891 auto tag = file.tag(); 892 if (tag != nullptr) 893 { 894 WriteXiphCommentAlbumCover(tag, album_cover_path, remove_exist); 895 bool saved = file.save(); 896 return saved; 897 } 898 return false; 899 } 900 901 bool CTagLibHelper::WriteOpusAlbumCover(const wstring & file_path, const wstring & album_cover_path, bool remove_exist) 902 { 903 Ogg::Opus::File file(file_path.c_str()); 904 if (!file.isValid()) 905 return false; 906 907 auto tag = file.tag(); 908 if (tag != nullptr) 909 { 910 WriteXiphCommentAlbumCover(tag, album_cover_path, remove_exist); 911 bool saved = file.save(); 912 return saved; 913 } 914 return false; 915 } 916 917 bool CTagLibHelper::WriteSpxAlbumCover(const wstring& file_path, const wstring& album_cover_path, bool remove_exist /*= true*/) 918 { 919 Ogg::Speex::File file(file_path.c_str()); 920 if (!file.isValid()) 921 return false; 922 923 auto tag = file.tag(); 924 if (tag != nullptr) 925 { 926 WriteXiphCommentAlbumCover(tag, album_cover_path, remove_exist); 927 bool saved = file.save(); 928 return saved; 929 } 930 return false; 931 } 932 933 bool CTagLibHelper::WriteAiffAlbumCover(const wstring& file_path, const wstring& album_cover_path, bool remove_exist /*= true*/) 934 { 935 RIFF::AIFF::File file(file_path.c_str()); 936 if (!file.isValid()) 937 return false; 938 939 //��ɾ��ר������ 940 auto id3v2tag = file.tag(); 941 if (remove_exist) 942 { 943 DeleteId3v2AlbumCover(id3v2tag); 944 } 945 if (!album_cover_path.empty()) 946 { 947 WriteId3v2AlbumCover(id3v2tag, album_cover_path); 948 } 949 bool saved = file.save(); 950 return saved; 951 } 952 953 bool CTagLibHelper::WriteMpcAlbumCover(const wstring& file_path, const wstring& album_cover_path, bool remove_exist /*= true*/) 954 { 955 MPC::File file(file_path.c_str()); 956 if (!file.isValid()) 957 return false; 958 959 auto tag = file.APETag(true); 960 WriteApeTagAlbumCover(tag, album_cover_path, remove_exist); 961 bool saved = file.save(); 962 return saved; 963 } 964 965 bool CTagLibHelper::WriteWavePackAlbumCover(const wstring& file_path, const wstring& album_cover_path, bool remove_exist /*= true*/) 966 { 967 WavPack::File file(file_path.c_str()); 968 if (!file.isValid()) 969 return false; 970 971 auto tag = file.APETag(true); 972 WriteApeTagAlbumCover(tag, album_cover_path, remove_exist); 973 bool saved = file.save(); 974 return saved; 975 } 976 977 bool CTagLibHelper::WriteMpegTag(SongInfo & song_info) 978 { 979 MPEG::File file(song_info.file_path.c_str()); 980 auto tag = file.tag(); 981 SongInfoToTag(song_info, tag); 982 int tags = MPEG::File::ID3v2; 983 //if (file.hasID3v1Tag()) 984 // tags |= MPEG::File::ID3v1; 985 if (file.hasAPETag()) 986 tags |= MPEG::File::APE; 987 bool saved = file.save(tags); 988 return saved; 989 } 990 991 bool CTagLibHelper::WriteFlacTag(SongInfo& song_info) 992 { 993 FLAC::File file(song_info.file_path.c_str()); 994 auto tag = file.tag(); 995 SongInfoToTag(song_info, tag); 996 bool saved = file.save(); 997 return saved; 998 } 999 1000 bool CTagLibHelper::WriteM4aTag(SongInfo & song_info) 1001 { 1002 MP4::File file(song_info.file_path.c_str()); 1003 auto tag = file.tag(); 1004 SongInfoToTag(song_info, tag); 1005 bool saved = file.save(); 1006 return saved; 1007 } 1008 1009 bool CTagLibHelper::WriteWavTag(SongInfo & song_info) 1010 { 1011 RIFF::WAV::File file(song_info.file_path.c_str()); 1012 auto tag = file.tag(); 1013 SongInfoToTag(song_info, tag); 1014 bool saved = file.save(); 1015 return saved; 1016 } 1017 1018 bool CTagLibHelper::WriteOggTag(SongInfo & song_info) 1019 { 1020 Vorbis::File file(song_info.file_path.c_str()); 1021 auto tag = file.tag(); 1022 SongInfoToTag(song_info, tag); 1023 bool saved = file.save(); 1024 return saved; 1025 } 1026 1027 bool CTagLibHelper::WriteApeTag(SongInfo& song_info) 1028 { 1029 APE::File file(song_info.file_path.c_str()); 1030 auto tag = file.tag(); 1031 SongInfoToTag(song_info, tag); 1032 bool saved = file.save(); 1033 return saved; 1034 } 1035 1036 bool CTagLibHelper::WriteMpcTag(SongInfo& song_info) 1037 { 1038 MPC::File file(song_info.file_path.c_str()); 1039 auto tag = file.tag(); 1040 SongInfoToTag(song_info, tag); 1041 bool saved = file.save(); 1042 return saved; 1043 } 1044 1045 bool CTagLibHelper::WriteOpusTag(SongInfo & song_info) 1046 { 1047 Ogg::Opus::File file(song_info.file_path.c_str()); 1048 auto tag = file.tag(); 1049 SongInfoToTag(song_info, tag); 1050 bool saved = file.save(); 1051 return saved; 1052 } 1053 1054 bool CTagLibHelper::WriteWavPackTag(SongInfo& song_info) 1055 { 1056 WavPack::File file(song_info.file_path.c_str()); 1057 auto tag = file.tag(); 1058 SongInfoToTag(song_info, tag); 1059 bool saved = file.save(); 1060 return saved; 1061 } 1062 1063 bool CTagLibHelper::WriteTtaTag(SongInfo& song_info) 1064 { 1065 TrueAudio::File file(song_info.file_path.c_str()); 1066 auto tag = file.tag(); 1067 SongInfoToTag(song_info, tag); 1068 bool saved = file.save(); 1069 return saved; 1070 } 1071 1072 bool CTagLibHelper::WriteAiffTag(SongInfo & song_info) 1073 { 1074 RIFF::AIFF::File file(song_info.file_path.c_str()); 1075 auto tag = file.tag(); 1076 SongInfoToTag(song_info, tag); 1077 bool saved = file.save(); 1078 return saved; 1079 } 1080 1081 bool CTagLibHelper::WriteAsfTag(SongInfo & song_info) 1082 { 1083 ASF::File file(song_info.file_path.c_str()); 1084 auto tag = file.tag(); 1085 SongInfoToTag(song_info, tag); 1086 bool saved = file.save(); 1087 return saved; 1088 } 1089 1090 bool CTagLibHelper::WriteSpxTag(SongInfo& song_info) 1091 { 1092 Ogg::Speex::File file(song_info.file_path.c_str()); 1093 auto tag = file.tag(); 1094 SongInfoToTag(song_info, tag); 1095 bool saved = file.save(); 1096 return saved; 1097 } 1098