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); }
int main(int argc, char *argv[]) { for(int i = 1; i < argc; i++) { cout << "******************** \"" << argv[i] << "\" ********************" << endl; TagLib::FileRef f(argv[i]); if(!f.isNull() && f.tag()) { TagLib::Tag *tag = f.tag(); cout << "-- TAG --" << endl; cout << "title - \"" << tag->title() << "\"" << endl; cout << "artist - \"" << tag->artist() << "\"" << endl; cout << "album artist - \"" << tag->albumArtist() << "\"" << endl; cout << "album - \"" << tag->album() << "\"" << endl; cout << "year - \"" << tag->year() << "\"" << endl; cout << "comment - \"" << tag->comment() << "\"" << endl; cout << "track - \"" << tag->track() << "\"" << endl; cout << "genre - \"" << tag->genre() << "\"" << endl; cout << "grouping - \"" << tag->grouping() << "\"" << endl; TagLib::Ogg::XiphComment *comment = NULL; TagLib::FLAC::File *flac = dynamic_cast<TagLib::FLAC::File *>(f.file()); if (flac) { cout << "flac:" << endl; cout << "id3v1 - \"" << flac->ID3v1Tag() << "\"" << endl; cout << "id3v2 - \"" << flac->ID3v2Tag() << "\"" << endl; cout << "xiph - \"" << flac->xiphComment() << "\"" << endl; comment = flac->xiphComment(); } if (!comment) { comment = dynamic_cast<TagLib::Ogg::XiphComment *>(tag); } if (comment) { TagLib::Ogg::FieldListMap fields = comment->fieldListMap(); for(TagLib::Ogg::FieldListMap::ConstIterator it = fields.begin(), end = fields.end(); it != end; it++) { if (!it->second.isEmpty()) cout << "xiph:" << it->first << " \"" << it->second[0].substr(0,3) << "\"" << endl; } } cout << "pictures- \"" << f.file()->pictures().size() << "\"" << endl; TagLib::File::PictureList l = f.file()->pictures(); for (TagLib::File::_PictureList::ConstIterator i = l.begin(), end = l.end(); i != end; i++) { cout << "\t" << (*i)->typeName() << ' ' << (*i)->mimeType() << ' ' << (*i)->base64data().size() << endl; } cout << "pictures- \"" << tag->pictures().size() << "\"" << endl; } if(!f.isNull() && f.audioProperties()) { TagLib::AudioProperties *properties = f.audioProperties(); int seconds = properties->length() % 60; int minutes = (properties->length() - seconds) / 60; cout << "-- AUDIO --" << endl; cout << "bitrate - " << properties->bitrate() << endl; cout << "sample rate - " << properties->sampleRate() << endl; cout << "channels - " << properties->channels() << endl; cout << "length - " << minutes << ":" << formatSeconds(seconds) << endl; } } return 0; }