QImage SoundSourceSndFile::parseCoverArt() { QImage coverArt; QString location = getFilename(); setType(location.section(".",-1).toLower()); const QByteArray qBAFilename(getFilename().toLocal8Bit()); if (getType() == "flac") { TagLib::FLAC::File f(qBAFilename.constData()); TagLib::ID3v2::Tag* id3v2 = f.ID3v2Tag(); if (id3v2) { coverArt = Mixxx::getCoverInID3v2Tag(*id3v2); } if (coverArt.isNull()) { TagLib::Ogg::XiphComment *xiph = f.xiphComment(); if (xiph) { coverArt = Mixxx::getCoverInXiphComment(*xiph); } } if (coverArt.isNull()) { TagLib::List<TagLib::FLAC::Picture*> covers = f.pictureList(); if (!covers.isEmpty()) { std::list<TagLib::FLAC::Picture*>::iterator it = covers.begin(); TagLib::FLAC::Picture* cover = *it; coverArt = QImage::fromData( QByteArray(cover->data().data(), cover->data().size())); } } } else if (getType() == "wav") { TagLib::RIFF::WAV::File f(qBAFilename.constData()); TagLib::ID3v2::Tag* id3v2 = f.tag(); if (id3v2) { coverArt = Mixxx::getCoverInID3v2Tag(*id3v2); } } else { // Try AIFF TagLib::RIFF::AIFF::File f(qBAFilename.constData()); TagLib::ID3v2::Tag* id3v2 = f.tag(); if (id3v2) { coverArt = Mixxx::getCoverInID3v2Tag(*id3v2); } } return coverArt; }
QImage SoundSourceFLAC::parseCoverArt() { QImage coverArt; setType("flac"); TagLib::FLAC::File f(m_qFilename.toLocal8Bit().constData()); coverArt = getCoverInID3v2Tag(f.ID3v2Tag()); if (coverArt.isNull()) { coverArt = getCoverInXiphComment(f.xiphComment()); } if (coverArt.isNull()) { TagLib::List<TagLib::FLAC::Picture*> covers = f.pictureList(); if (!covers.isEmpty()) { std::list<TagLib::FLAC::Picture*>::iterator it = covers.begin(); TagLib::FLAC::Picture* cover = *it; coverArt = QImage::fromData( QByteArray(cover->data().data(), cover->data().size())); } } return coverArt; }
bool mediaFLAC(Artwork *art, const char *filePath) { TagLib::FLAC::File f(filePath); if (!f.tag()) { return false; } if (!mediaTag(art, &f)) { return false; } art->filetype = FILETYPE_FLAC; #if 0 const TagLib::List<TagLib::FLAC::Picture*> picturelist = f->pictureList(); for(TagLib::List<TagLib::FLAC::Picture*>::ConstIterator it = picturelist.begin(); it != picturelist.end(); it++) { TagLib::FLAC::Picture *picture = (*it); if (picture) { if (picture->type() == TagLib::FLAC::Picture::FileIcon || picture->type() == TagLib::FLAC::Picture::OtherFileIcon || picture->type( )== TagLib::FLAC::Picture::ColouredFish) { // skip! } else { if (!art->hasCover()) { saveImage(art, (const uchar *) picture->data().data(), picture->data().size()); } break; } } } #endif return art; }
QByteArray TagReader::LoadEmbeddedArt(const QString& filename) const { if (filename.isEmpty()) return QByteArray(); qLog(Debug) << "Loading art from" << filename; #ifdef Q_OS_WIN32 TagLib::FileRef ref(filename.toStdWString().c_str()); #else TagLib::FileRef ref(QFile::encodeName(filename).constData()); #endif if (ref.isNull() || !ref.file()) return QByteArray(); // MP3 TagLib::MPEG::File* file = dynamic_cast<TagLib::MPEG::File*>(ref.file()); if (file && file->ID3v2Tag()) { TagLib::ID3v2::FrameList apic_frames = file->ID3v2Tag()->frameListMap()["APIC"]; if (apic_frames.isEmpty()) return QByteArray(); TagLib::ID3v2::AttachedPictureFrame* pic = static_cast<TagLib::ID3v2::AttachedPictureFrame*>(apic_frames.front()); return QByteArray((const char*)pic->picture().data(), pic->picture().size()); } // Ogg vorbis/speex TagLib::Ogg::XiphComment* xiph_comment = dynamic_cast<TagLib::Ogg::XiphComment*>(ref.file()->tag()); if (xiph_comment) { TagLib::Ogg::FieldListMap map = xiph_comment->fieldListMap(); // Other than the below mentioned non-standard COVERART, // METADATA_BLOCK_PICTURE // is the proposed tag for cover pictures. // (see http://wiki.xiph.org/VorbisComment#METADATA_BLOCK_PICTURE) if (map.contains("METADATA_BLOCK_PICTURE")) { TagLib::StringList pict_list = map["METADATA_BLOCK_PICTURE"]; for (std::list<TagLib::String>::iterator it = pict_list.begin(); it != pict_list.end(); ++it) { QByteArray data(QByteArray::fromBase64(it->toCString())); TagLib::ByteVector tdata(data.data(), data.size()); TagLib::FLAC::Picture p(tdata); if (p.type() == TagLib::FLAC::Picture::FrontCover) return QByteArray(p.data().data(), p.data().size()); } // If there was no specific front cover, just take the first picture QByteArray data(QByteArray::fromBase64( map["METADATA_BLOCK_PICTURE"].front().toCString())); TagLib::ByteVector tdata(data.data(), data.size()); TagLib::FLAC::Picture p(tdata); return QByteArray(p.data().data(), p.data().size()); } // Ogg lacks a definitive standard for embedding cover art, but it seems // b64 encoding a field called COVERART is the general convention if (!map.contains("COVERART")) return QByteArray(); return QByteArray::fromBase64(map["COVERART"].toString().toCString()); } #ifdef TAGLIB_HAS_FLAC_PICTURELIST // Flac TagLib::FLAC::File* flac_file = dynamic_cast<TagLib::FLAC::File*>(ref.file()); if (flac_file && flac_file->xiphComment()) { TagLib::List<TagLib::FLAC::Picture*> pics = flac_file->pictureList(); if (!pics.isEmpty()) { // Use the first picture in the file - this could be made cleverer and // pick the front cover if it's present. std::list<TagLib::FLAC::Picture*>::iterator it = pics.begin(); TagLib::FLAC::Picture* picture = *it; return QByteArray(picture->data().data(), picture->data().size()); } } #endif // MP4/AAC TagLib::MP4::File* aac_file = dynamic_cast<TagLib::MP4::File*>(ref.file()); if (aac_file) { TagLib::MP4::Tag* tag = aac_file->tag(); const TagLib::MP4::ItemListMap& items = tag->itemListMap(); TagLib::MP4::ItemListMap::ConstIterator it = items.find("covr"); if (it != items.end()) { const TagLib::MP4::CoverArtList& art_list = it->second.toCoverArtList(); if (!art_list.isEmpty()) { // Just take the first one for now const TagLib::MP4::CoverArt& art = art_list.front(); return QByteArray(art.data().data(), art.data().size()); } } } return QByteArray(); }