/** * Get the various artist information form a tag. * * @param filetype the type-id for the file that is being processed * @param tagtype the tag-type to use (if more than one are used per filetype) * @param tag the tag-data from taglib * * @return a proper multi-artist data field or a NULL pointer. * @sideeffects none */ const char * taggit_tag_va(enum file_type filetype, int tagtype, TagLib_Tag *tag) { /* * At this point, we already figured out the file type *and* decided which * tag to read from the file. `filetype' and `tagtype' give us hints into * the right direction. We *must* follow these hints or things will blow * up. */ TagLib::APE::Tag *ape; TagLib::ID3v2::Tag *v2; TagLib::Ogg::XiphComment *ogg; const char *ret; ret = (const char *)NULL; switch (filetype) { case FT_MPEG: if (tagtype & MP3_ID3V2) { /** * @TODO Add support for TCMP (and maybe TCP) frames. * It's probably best to only check for those if TPE2 is empty, * because otherwise we already consider the track part of a * compilation. */ v2 = reinterpret_cast<TagLib::ID3v2::Tag *>(tag); if (v2->frameListMap()["TPE2"].isEmpty()) break; ret = xstrdup( v2->frameListMap()["TPE2"].front()->toString().toCString()); } else if (tagtype & MP3_APE) { ape = reinterpret_cast<TagLib::APE::Tag *>(tag); if (ape->itemListMap()["ALBUMARTIST"].isEmpty()) break; ret = xstrdup( ape->itemListMap()["ALBUMARTIST"].toString().toCString()); } /* Don't care about ID3v1 */ break; case FT_OGGVORBIS: /* @FALLTHROUGH@ */ case FT_OGGFLAC: /* ogg* files share the same tag format */ ogg = reinterpret_cast<TagLib::Ogg::XiphComment *>(tag); if (ogg->fieldListMap()["ALBUMARTIST"].isEmpty()) break; ret = xstrdup( ogg->fieldListMap()["ALBUMARTIST"].toString().toCString()); break; case FT_FLAC: /* AFAIK, there is no native FLAC tag format */ break; default: break; } return ret; }
/** * Change tag type informmation in a struct taggit_list * * A string is created for the tagtypes entry. It will be a comma seperated * list of tags found within the given mp3 file. This string is dynamically * allocated and needs to be freed if it is not in use anymore (which will be * taken care of when taglist_destroy() is called). * * Secondly, the readmap is checked for which of the existing tag types should * be read. This information is then stored in the tagtype entry of the struct. * * @param f TagLib_File pointer to check * @param lst A pointer to the taggit_list structure to change * * @return void (see description) * @sideeffects none */ void mp3_tagtypes(TagLib_File *f, struct taggit_list *lst) { TagLib::MPEG::File::File *file; TagLib::ID3v1::Tag *v1; TagLib::ID3v2::Tag *v2; TagLib::APE::Tag *ape; std::string tmp; int types; char *rc; file = reinterpret_cast<TagLib::MPEG::File::File *>(f); types = MP3_NO_TAGS; tmp = ""; ape = file->APETag(); if (ape != NULL && !(ape->isEmpty() && ape->itemListMap()["ALBUMARTIST"].isEmpty())) { tmp += "apetag"; types |= MP3_APE; } v1 = file->ID3v1Tag(); if (v1 != NULL && !v1->isEmpty()) { if (tmp != "") tmp += ","; tmp = "id3v1"; types |= MP3_ID3V1; } v2 = file->ID3v2Tag(); if (v2 != NULL && !v2->isEmpty()) { if (tmp != "") tmp += ","; tmp += "id3v2"; types |= MP3_ID3V2; } if (tmp == "") tmp = "(no tags)"; rc = xstrdup(tmp.c_str()); if (errno == ENOMEM) { fprintf(stderr, "Out of memory. Aborting.\n"); exit(EXIT_FAILURE); } lst->tagtypes = rc; lst->tagtype = setup_please_read((char*)"mp3", types); }
/** * Set the file-type specific `compilation' tag. * * See the discussion on top of this file about which tag is used * for which file-type. * * @param file taggit's file-data structure for the processed file * @param tag the tag-data decoded by `taglib_file_tag()' * @param value the string the user wants to set this tag to * * @return void * @sideeffects none */ void taggit_tag_set_compilation(struct taggit_file *file, TagLib_Tag *tag, const char *value) { TagLib::APE::Tag *ape; TagLib::ID3v2::Tag *v2; TagLib::Ogg::XiphComment *ogg; const char *ret; TagLib::MPEG::File::File *f; int mask; ret = (const char *)NULL; switch (file->type) { case FT_MPEG: f = reinterpret_cast<TagLib::MPEG::File::File *>(file->data); mask = setup_get_write_mask(FT_MPEG); if (mask & MP3_ID3V2) { v2 = f->ID3v2Tag(); v2->removeFrames("TPE2"); /* * @TODO: I don't know how to figure out the proper `encoding' * value here. Should we look at the `unicodeStrings' * variable from taglib? */ TagLib::ID3v2::TextIdentificationFrame *frame = new TagLib::ID3v2::TextIdentificationFrame( "TPE2", TagLib::String::Latin1); frame->setText(value); v2->addFrame(frame); } if (mask & MP3_APE) { ape = f->APETag(); ape->addValue("ALBUMARTIST", value, true); } break; case FT_OGGVORBIS: /* @FALLTHROUGH@ */ case FT_OGGFLAC: ogg = reinterpret_cast<TagLib::Ogg::XiphComment *>(tag); ogg->addField("ALBUMARTIST", value, true); break; default: break; } }
void TakSource::fetchTags() { int fd = fileno(m_fp.get()); util::FilePositionSaver _(fd); lseek(fd, 0, SEEK_SET); TagLibX::FDIOStreamReader stream(fd); TagLib::APE::File file(&stream, false); std::map<std::string, std::string> tags; std::wstring cuesheet; TagLib::APE::Tag *tag = file.APETag(false); const TagLib::APE::ItemListMap &itemListMap = tag->itemListMap(); TagLib::APE::ItemListMap::ConstIterator it; for (it = itemListMap.begin(); it != itemListMap.end(); ++it) { if (it->second.type() != TagLib::APE::Item::Text) continue; std::string key = it->first.toCString(); std::wstring value = it->second.toString().toWString(); tags[key] = strutil::w2us(value); } TextBasedTag::normalizeTags(tags, &m_tags); }
QList<FileInfo *> DecoderMPCFactory::createPlayList(const QString &fileName, bool useMetaData, QStringList *) { FileInfo *info = new FileInfo(fileName); #if (TAGLIB_MAJOR_VERSION > 1) || ((TAGLIB_MAJOR_VERSION == 1) && (TAGLIB_MINOR_VERSION >= 8)) TagLib::FileStream stream(fileName.toLocal8Bit().constData(), true); TagLib::MPC::File fileRef(&stream); #else TagLib::MPC::File fileRef(fileName.toLocal8Bit().constData()); #endif TagLib::APE::Tag *tag = useMetaData ? fileRef.APETag() : 0; if (tag && !tag->isEmpty()) { info->setMetaData(Qmmp::ALBUM, QString::fromUtf8(tag->album().toCString(true)).trimmed()); info->setMetaData(Qmmp::ARTIST, QString::fromUtf8(tag->artist().toCString(true)).trimmed()); info->setMetaData(Qmmp::COMMENT, QString::fromUtf8(tag->comment().toCString(true)).trimmed()); info->setMetaData(Qmmp::GENRE, QString::fromUtf8(tag->genre().toCString(true)).trimmed()); info->setMetaData(Qmmp::TITLE, QString::fromUtf8(tag->title().toCString(true)).trimmed()); info->setMetaData(Qmmp::YEAR, tag->year()); info->setMetaData(Qmmp::TRACK, tag->track()); } if (fileRef.audioProperties()) info->setLength(fileRef.audioProperties()->length()); //additional metadata if(tag) { TagLib::APE::Item fld; if(!(fld = tag->itemListMap()["ALBUM ARTIST"]).isEmpty()) info->setMetaData(Qmmp::ALBUMARTIST, QString::fromUtf8(fld.toString().toCString(true)).trimmed()); if(!(fld = tag->itemListMap()["COMPOSER"]).isEmpty()) info->setMetaData(Qmmp::COMPOSER, QString::fromUtf8(fld.toString().toCString(true)).trimmed()); } QList <FileInfo*> list; list << info; return list; }
int TagLibMetadata::setGrouping(const QString& grp){ if(f == NULL || !f->isValid()){ qDebug("Cannot set grouping tag on invalid file object"); return 1; } TagLib::MPEG::File* fileTestMpeg = dynamic_cast<TagLib::MPEG::File*>(f); if(fileTestMpeg != NULL){ TagLib::ID3v2::Tag* tagTestId3v2 = fileTestMpeg->ID3v2Tag(); if(tagTestId3v2 != NULL){ TagLib::ID3v2::Frame* frm = new TagLib::ID3v2::TextIdentificationFrame("TIT1"); frm->setText(TagLib::String(grp.toUtf8().data())); tagTestId3v2->removeFrames("TIT1"); tagTestId3v2->addFrame(frm); f->save(); return 0; }else{ TagLib::ID3v1::Tag* tagTestId3v1 = fileTestMpeg->ID3v1Tag(); if(tagTestId3v1 != NULL){ #ifdef Q_OS_WIN qDebug("ID3v1 does not support the Grouping tag"); #else qDebug("ID3v1 does not support the Grouping tag (%s)",f->name()); #endif return 1; } } } TagLib::RIFF::AIFF::File* fileTestAiff = dynamic_cast<TagLib::RIFF::AIFF::File*>(f); if(fileTestAiff != NULL){ TagLib::ID3v2::Tag* tagTestId3v2 = fileTestAiff->tag(); if(tagTestId3v2 != NULL){ TagLib::ID3v2::Frame* frm = new TagLib::ID3v2::TextIdentificationFrame("TIT1"); frm->setText(TagLib::String(grp.toUtf8().data())); tagTestId3v2->removeFrames("TIT1"); tagTestId3v2->addFrame(frm); f->save(); return 0; } } TagLib::RIFF::WAV::File* fileTestWav = dynamic_cast<TagLib::RIFF::WAV::File*>(f); if(fileTestWav != NULL){ TagLib::ID3v2::Tag* tagTestId3v2 = fileTestWav->tag(); if(tagTestId3v2 != NULL){ TagLib::ID3v2::Frame* frm = new TagLib::ID3v2::TextIdentificationFrame("TIT1"); frm->setText(TagLib::String(grp.toUtf8().data())); tagTestId3v2->removeFrames("TIT1"); tagTestId3v2->addFrame(frm); f->save(); return 0; } } TagLib::MP4::Tag* tagTestMp4 = dynamic_cast<TagLib::MP4::Tag*>(f->tag()); if(tagTestMp4 != NULL){ TagLib::StringList sl(TagLib::String(grp.toUtf8().data())); tagTestMp4->itemListMap()["\251grp"] = sl; tagTestMp4->save(); f->save(); return 0; } TagLib::ASF::Tag* tagTestAsf = dynamic_cast<TagLib::ASF::Tag*>(f->tag()); if(tagTestAsf != NULL){ tagTestAsf->setAttribute("WM/ContentGroupDescription",TagLib::String(grp.toUtf8().data())); f->save(); return 0; } TagLib::APE::Tag* tagTestApe = dynamic_cast<TagLib::APE::Tag*>(f->tag()); if(tagTestApe != NULL){ tagTestApe->addValue("GROUPING",TagLib::String(grp.toUtf8().data())); f->save(); return 0; } #ifdef Q_OS_WIN qDebug("Grouping tag write failed all tests"); #else qDebug("Grouping tag write failed all tests on %s",f->name()); #endif return 1; }
QString TagLibMetadata::getGrouping() const{ if(f == NULL || !f->isValid()) return ""; TagLib::MPEG::File* fileTestMpeg = dynamic_cast<TagLib::MPEG::File*>(f); if(fileTestMpeg != NULL){ TagLib::ID3v2::Tag* tagTestId3v2 = fileTestMpeg->ID3v2Tag(); if(tagTestId3v2 != NULL){ TagLib::ID3v2::FrameList l = tagTestId3v2->frameListMap()["TIT1"]; if(!l.isEmpty()){ TagLib::String out = l.front()->toString(); return QString::fromUtf8((out.toCString())); } return ""; } TagLib::ID3v1::Tag* tagTestId3v1 = fileTestMpeg->ID3v1Tag(); if(tagTestId3v1 != NULL){ #ifdef Q_OS_WIN qDebug("ID3v1 does not support the Grouping tag"); #else qDebug("ID3v1 does not support the Grouping tag (%s)",f->name()); #endif return "N/A"; } } TagLib::RIFF::AIFF::File* fileTestAiff = dynamic_cast<TagLib::RIFF::AIFF::File*>(f); if(fileTestAiff != NULL){ TagLib::ID3v2::Tag* tagTestId3v2 = fileTestAiff->tag(); if(tagTestId3v2 != NULL){ TagLib::ID3v2::FrameList l = tagTestId3v2->frameListMap()["TIT1"]; if(!l.isEmpty()){ TagLib::String out = l.front()->toString(); return QString::fromUtf8((out.toCString())); } return ""; } } TagLib::RIFF::WAV::File* fileTestWav = dynamic_cast<TagLib::RIFF::WAV::File*>(f); if(fileTestWav != NULL){ TagLib::ID3v2::Tag* tagTestId3v2 = fileTestWav->tag(); if(tagTestId3v2 != NULL){ TagLib::ID3v2::FrameList l = tagTestId3v2->frameListMap()["TIT1"]; if(!l.isEmpty()){ TagLib::String out = l.front()->toString(); return QString::fromUtf8((out.toCString())); } return ""; } } TagLib::MP4::Tag* tagTestMp4 = dynamic_cast<TagLib::MP4::Tag*>(f->tag()); if(tagTestMp4 != NULL){ TagLib::MP4::Item m = tagTestMp4->itemListMap()["\251grp"]; if(m.isValid()){ TagLib::String out = m.toStringList().front(); return QString::fromUtf8((out.toCString())); } return ""; } TagLib::ASF::Tag* tagTestAsf = dynamic_cast<TagLib::ASF::Tag*>(f->tag()); if(tagTestAsf != NULL){ TagLib::ASF::AttributeList l = tagTestAsf->attributeListMap()["WM/ContentGroupDescription"]; if(!l.isEmpty()){ TagLib::String out = l.front().toString(); return QString::fromUtf8((out.toCString())); } return ""; } TagLib::APE::Tag* tagTestApe = dynamic_cast<TagLib::APE::Tag*>(f->tag()); if(tagTestApe != NULL){ TagLib::APE::Item m = tagTestApe->itemListMap()["Grouping"]; if(!m.isEmpty()){ TagLib::String out = m.toStringList().front(); return QString::fromUtf8((out.toCString())); } return ""; } #ifdef Q_OS_WIN qDebug("Grouping tag read failed all tests"); #else qDebug("Grouping tag read failed all tests on %s",f->name()); #endif return "N/A"; }