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