QString FileHelper::extractFlacFeature(const QString &featureToExtract) const { QString feature; if (TagLib::FLAC::File *flacFile = static_cast<TagLib::FLAC::File*>(_file)) { if (flacFile->ID3v2Tag()) { QString key = this->convertKeyToID3v2Key(featureToExtract); TagLib::ID3v2::FrameList l = flacFile->ID3v2Tag()->frameListMap()[key.toStdString().data()]; // Fallback to the generic map in case we didn't find the matching key if (l.isEmpty()) { TagLib::StringList list = flacFile->properties()[featureToExtract.toStdString()]; if (!list.isEmpty()) { feature = list.front().toCString(true); } } else { feature = QString(l.front()->toString().toCString(true)); } } else if (flacFile->ID3v1Tag()) { qDebug() << Q_FUNC_INFO << "Not yet implemented for ID3v1Tag FLAC file"; } else if (flacFile->xiphComment()) { const TagLib::Ogg::FieldListMap map = flacFile->xiphComment()->fieldListMap(); if (!map[featureToExtract.toStdString().data()].isEmpty()) { feature = QString(map[featureToExtract.toStdString().data()].front().toCString(true)); } } } return feature; }
/** Convert the existing rating number into a smaller range from 1 to 5. */ int FileHelper::rating() const { int r = -1; /// TODO other types? switch (_fileType) { case EXT_MP3: { TagLib::MPEG::File *mpegFile = static_cast<TagLib::MPEG::File*>(_file); if (mpegFile && mpegFile->hasID3v2Tag()) { r = this->ratingForID3v2(mpegFile->ID3v2Tag()); } break; } case EXT_FLAC: { if (TagLib::FLAC::File *flacFile = static_cast<TagLib::FLAC::File*>(_file)) { if (flacFile->hasID3v2Tag()) { r = this->ratingForID3v2(flacFile->ID3v2Tag()); } else if (flacFile->hasID3v1Tag()) { qDebug() << Q_FUNC_INFO << "Not implemented (FLAC ID3v1)"; } else if (flacFile->hasXiphComment()) { TagLib::StringList list = flacFile->xiphComment()->fieldListMap()["RATING"]; if (!list.isEmpty()) { r = list.front().toInt(); } } } break; } default: break; } return r; }
QString FileHelper::extractGenericFeature(const QString &featureToExtract) const { QString feature; TagLib::PropertyMap p = _file->properties(); if (p.contains(featureToExtract.toStdString().data())) { TagLib::StringList list = p[featureToExtract.toStdString().data()]; if (!list.isEmpty()) { feature = list.front().toCString(true); } } return feature; }
QPixmap VorbisMetaDataModel::cover() { TagLib::Ogg::Vorbis::File file(m_path.toLocal8Bit().constData()); TagLib::Ogg::XiphComment *tag = file.tag(); if(!tag) return QPixmap(); TagLib::StringList list = tag->fieldListMap()["METADATA_BLOCK_PICTURE"]; if(list.isEmpty()) return QPixmap(); for(uint i = 0; i < list.size(); ++i) { TagLib::String value = list[i]; QByteArray block = QByteArray::fromBase64(TStringToQString_qt4(value).toAscii()); if(block.size() < 32) continue; qint64 pos = 0; if(readPictureBlockField(block, pos) != 3) //picture type, use front cover only continue; pos += 4; int mimeLength = readPictureBlockField(block, pos); //mime type length pos += 4; pos += mimeLength; //skip mime type int descLength = readPictureBlockField(block, pos); //description length pos += 4; pos += descLength; //skip description pos += 4; //width pos += 4; //height pos += 4; //color depth pos += 4; //the number of colors used int length = readPictureBlockField(block, pos); //picture size pos += 4; QPixmap cover; cover.loadFromData(block.mid(pos, length)); //read binary picture data return cover; } return QPixmap(); }
void TagLibExtractor::extract(ExtractionResult* result) { const QString fileUrl = result->inputUrl(); const QString mimeType = result->inputMimetype(); TagLib::FileRef file(fileUrl.toUtf8().constData(), true); if (file.isNull()) { return; } TagLib::Tag* tags = file.tag(); result->addType(Type::Audio); TagLib::String artists; TagLib::String albumArtists; TagLib::String composers; TagLib::String lyricists; TagLib::StringList genres; // Handling multiple tags in mpeg files. if ((mimeType == QLatin1String("audio/mpeg")) || (mimeType == QLatin1String("audio/mpeg3")) || (mimeType == QLatin1String("audio/x-mpeg"))) { TagLib::MPEG::File mpegFile(fileUrl.toUtf8().constData(), true); if (mpegFile.ID3v2Tag() && !mpegFile.ID3v2Tag()->isEmpty()) { TagLib::ID3v2::FrameList lstID3v2; // Artist. lstID3v2 = mpegFile.ID3v2Tag()->frameListMap()["TPE1"]; if (!lstID3v2.isEmpty()) { for (TagLib::ID3v2::FrameList::ConstIterator it = lstID3v2.begin(); it != lstID3v2.end(); ++it) { if (!artists.isEmpty()) { artists += ", "; } artists += (*it)->toString(); } } // Album Artist. lstID3v2 = mpegFile.ID3v2Tag()->frameListMap()["TPE2"]; if (!lstID3v2.isEmpty()) { for (TagLib::ID3v2::FrameList::ConstIterator it = lstID3v2.begin(); it != lstID3v2.end(); ++it) { if (!albumArtists.isEmpty()) { albumArtists += ", "; } albumArtists += (*it)->toString(); } } // Composer. lstID3v2 = mpegFile.ID3v2Tag()->frameListMap()["TCOM"]; if (!lstID3v2.isEmpty()) { for (TagLib::ID3v2::FrameList::ConstIterator it = lstID3v2.begin(); it != lstID3v2.end(); ++it) { if (!composers.isEmpty()) { composers += ", "; } composers += (*it)->toString(); } } // Lyricist. lstID3v2 = mpegFile.ID3v2Tag()->frameListMap()["TEXT"]; if (!lstID3v2.isEmpty()) { for (TagLib::ID3v2::FrameList::ConstIterator it = lstID3v2.begin(); it != lstID3v2.end(); ++it) { if (!lyricists.isEmpty()) { lyricists += ", "; } lyricists += (*it)->toString(); } } // Genre. lstID3v2 = mpegFile.ID3v2Tag()->frameListMap()["TCON"]; if (!lstID3v2.isEmpty()) { for (TagLib::ID3v2::FrameList::ConstIterator it = lstID3v2.begin(); it != lstID3v2.end(); ++it) { genres.append((*it)->toString()); } } } } // Handling multiple tags in Ogg containers. { TagLib::Ogg::FieldListMap lstOgg; // FLAC files. if (mimeType == QLatin1String("audio/flac")) { TagLib::FLAC::File flacFile(fileUrl.toUtf8().constData(), true); if (flacFile.xiphComment() && !flacFile.xiphComment()->isEmpty()) { lstOgg = flacFile.xiphComment()->fieldListMap(); } } // Vorbis files. if (mimeType == QLatin1String("audio/ogg") || mimeType == QLatin1String("audio/x-vorbis+ogg")) { TagLib::Ogg::Vorbis::File oggFile(fileUrl.toUtf8().constData(), true); if (oggFile.tag() && !oggFile.tag()->isEmpty()) { lstOgg = oggFile.tag()->fieldListMap(); } } // Opus files. if (mimeType == QLatin1String("audio/opus") || mimeType == QLatin1String("audio/x-opus+ogg")) { TagLib::Ogg::Opus::File opusFile(fileUrl.toUtf8().constData(), true); if (opusFile.tag() && !opusFile.tag()->isEmpty()) { lstOgg = opusFile.tag()->fieldListMap(); } } // Handling OGG container tags. if (!lstOgg.isEmpty()) { TagLib::Ogg::FieldListMap::ConstIterator itOgg; // Artist. itOgg = lstOgg.find("ARTIST"); if (itOgg != lstOgg.end()) { if (!artists.isEmpty()) { artists += ", "; } artists += (*itOgg).second.toString(", "); } // Album Artist. itOgg = lstOgg.find("ALBUMARTIST"); if (itOgg != lstOgg.end()) { if (!albumArtists.isEmpty()) { albumArtists += ", "; } albumArtists += (*itOgg).second.toString(", "); } // Composer. itOgg = lstOgg.find("COMPOSER"); if (itOgg != lstOgg.end()) { if (!composers.isEmpty()) { composers += ", "; } composers += (*itOgg).second.toString(", "); } // Lyricist. itOgg = lstOgg.find("LYRICIST"); if (itOgg != lstOgg.end()) { if (!lyricists.isEmpty()) { lyricists += ", "; } lyricists += (*itOgg).second.toString(", "); } // Genre. itOgg = lstOgg.find("GENRE"); if (itOgg != lstOgg.end()) { genres.append((*itOgg).second); } } } // Handling multiple tags in Musepack files. if (mimeType == QLatin1String("audio/x-musepack")) { TagLib::MPC::File mpcFile(fileUrl.toUtf8().constData(), true); if (mpcFile.tag() && !mpcFile.tag()->isEmpty()) { TagLib::APE::ItemListMap lstMusepack = mpcFile.APETag()->itemListMap(); TagLib::APE::ItemListMap::ConstIterator itMPC; // Artist. itMPC = lstMusepack.find("ARTIST"); if (itMPC != lstMusepack.end()) { if (!artists.isEmpty()) { artists += ", "; } artists += (*itMPC).second.toString(); } // Album Artist. itMPC = lstMusepack.find("ALBUMARTIST"); if (itMPC != lstMusepack.end()) { if(!albumArtists.isEmpty()) { albumArtists += ", "; } albumArtists += (*itMPC).second.toString(); } // Composer. itMPC = lstMusepack.find("COMPOSER"); if (itMPC != lstMusepack.end()) { if (!composers.isEmpty()) { composers += ", "; } composers += (*itMPC).second.toString(); } // Lyricist. itMPC = lstMusepack.find("LYRICIST"); if (itMPC != lstMusepack.end()) { if (!lyricists.isEmpty()) { lyricists += ", "; } lyricists += (*itMPC).second.toString(); } // Genre. itMPC = lstMusepack.find("GENRE"); if (itMPC != lstMusepack.end()) { genres.append((*itMPC).second.toString()); } } } if (!tags->isEmpty()) { QString title = t2q(tags->title()); if (!title.isEmpty()) { result->add(Property::Title, title); } QString comment = t2q(tags->comment()); if (!comment.isEmpty()) { result->add(Property::Comment, comment); } if (genres.isEmpty()) { genres.append(tags->genre()); } for (uint i = 0; i < genres.size(); i++) { QString genre = t2q(genres[i]).trimmed(); // Convert from int bool ok = false; int genreNum = genre.toInt(&ok); if (ok) { genre = t2q(TagLib::ID3v1::genre(genreNum)); } result->add(Property::Genre, genre); } QString artistString; if (artists.isEmpty()) { artistString = t2q(tags->artist()); } else { artistString = t2q(artists).trimmed(); } QStringList artists = contactsFromString(artistString); foreach(const QString& artist, artists) { result->add(Property::Artist, artist); }