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