Ejemplo n.º 1
0
void FileHelper::setRatingForID3v2(int rating, TagLib::ID3v2::Tag *tag)
{
	TagLib::ID3v2::FrameList l = tag->frameListMap()["POPM"];
	// If one wants to remove the existing rating
	if (rating == 0 && !l.isEmpty()) {
		tag->removeFrame(l.front());
	} else {
		TagLib::ID3v2::PopularimeterFrame *pf = nullptr;
		if (l.isEmpty()) {
			pf = new TagLib::ID3v2::PopularimeterFrame();
			tag->addFrame(pf);
		} else {
			pf = static_cast<TagLib::ID3v2::PopularimeterFrame*>(l.front());
		}
		switch (rating) {
		case 1:
			pf->setRating(1);
			break;
		case 2:
			pf->setRating(64);
			break;
		case 3:
			pf->setRating(128);
			break;
		case 4:
			pf->setRating(196);
			break;
		case 5:
			pf->setRating(255);
			break;
		}
	}
}
Ejemplo n.º 2
0
bool SoundSource::processID3v2Tag(TagLib::ID3v2::Tag* id3v2) {

    // Print every frame in the file.
    if (s_bDebugMetadata) {
        TagLib::ID3v2::FrameList::ConstIterator it = id3v2->frameList().begin();
        for(; it != id3v2->frameList().end(); it++) {
            qDebug() << "ID3V2" << (*it)->frameID().data() << "-"
                    << TStringToQString((*it)->toString());
        }
    }

    TagLib::ID3v2::FrameList bpmFrame = id3v2->frameListMap()["TBPM"];
    if (!bpmFrame.isEmpty()) {
        QString sBpm = TStringToQString(bpmFrame.front()->toString());
        processBpmString("ID3v2", sBpm);
    }

    TagLib::ID3v2::FrameList keyFrame = id3v2->frameListMap()["TKEY"];
    if (!keyFrame.isEmpty()) {
        QString sKey = TStringToQString(keyFrame.front()->toString());
        setKey(sKey);
    }
    // Foobar2000-style ID3v2.3.0 tags
    // TODO: Check if everything is ok.
    TagLib::ID3v2::FrameList frames = id3v2->frameListMap()["TXXX"];
    for ( TagLib::ID3v2::FrameList::Iterator it = frames.begin(); it != frames.end(); ++it ) {
        TagLib::ID3v2::UserTextIdentificationFrame* ReplayGainframe =
                dynamic_cast<TagLib::ID3v2::UserTextIdentificationFrame*>( *it );
        if ( ReplayGainframe && ReplayGainframe->fieldList().size() >= 2 )
        {
            QString desc = TStringToQString( ReplayGainframe->description() ).toLower();
            if ( desc == "replaygain_album_gain" ){
                QString sReplayGain = TStringToQString( ReplayGainframe->fieldList()[1]);
                parseReplayGainString(sReplayGain);
            }
            if ( desc == "replaygain_track_gain" ){
                QString sReplayGain = TStringToQString( ReplayGainframe->fieldList()[1]);
                parseReplayGainString(sReplayGain);
            }
        }
    }
    TagLib::ID3v2::FrameList composerFrame = id3v2->frameListMap()["TCOM"];
    if (!composerFrame.isEmpty()) {
        QString sComposer = TStringToQString(composerFrame.front()->toString());
        setComposer(sComposer);
    }

    return true;
}
Ejemplo n.º 3
0
void mttFile::checkEncodings( void )
{
	fileref = new TagLib::FileRef( QFile::encodeName( fname ).constData() );

    if ( isMpeg() ) {
        TagLib::MPEG::File *f = dynamic_cast<TagLib::MPEG::File *>(fileref->file());

        if ( f->ID3v2Tag() ) {
            TagLib::ID3v2::FrameList l = f->ID3v2Tag()->frameListMap()["TALB"];
            if ( !l.isEmpty() ) {
                TagLib::ID3v2::TextIdentificationFrame *tf = dynamic_cast<TagLib::ID3v2::TextIdentificationFrame *>(l.front());
                if ( tf && tf->textEncoding() != TagLib::String::UTF8 )
                    tf->setTextEncoding( TagLib::String::UTF8 );
            }

            l = f->ID3v2Tag()->frameListMap()["TIT2"];
            if ( !l.isEmpty() ) {
                TagLib::ID3v2::TextIdentificationFrame *tf = dynamic_cast<TagLib::ID3v2::TextIdentificationFrame *>(l.front());
                if ( tf && tf->textEncoding() != TagLib::String::UTF8 )
                    tf->setTextEncoding( TagLib::String::UTF8 );
            }

            l = f->ID3v2Tag()->frameListMap()["TPE1"];
            if ( !l.isEmpty() ) {
                TagLib::ID3v2::TextIdentificationFrame *tf = dynamic_cast<TagLib::ID3v2::TextIdentificationFrame *>(l.front());
                if ( tf && tf->textEncoding() != TagLib::String::UTF8 )
                    tf->setTextEncoding( TagLib::String::UTF8 );
            }

            l = f->ID3v2Tag()->frameListMap()["TCON"];
            if ( !l.isEmpty() ) {
                TagLib::ID3v2::TextIdentificationFrame *tf = dynamic_cast<TagLib::ID3v2::TextIdentificationFrame *>(l.front());
                if ( tf && tf->textEncoding() != TagLib::String::UTF8 )
                    tf->setTextEncoding( TagLib::String::UTF8 );
            }

            l = f->ID3v2Tag()->frameListMap()["COMM"];
            if ( !l.isEmpty() ) {
                TagLib::ID3v2::TextIdentificationFrame *tf = dynamic_cast<TagLib::ID3v2::TextIdentificationFrame *>(l.front());
                if ( tf && tf->textEncoding() != TagLib::String::UTF8 )
                    tf->setTextEncoding( TagLib::String::UTF8 );
            }
        }
    }

    delete fileref;
    fileref = NULL;
}
Ejemplo n.º 4
0
int FileHelper::ratingForID3v2(TagLib::ID3v2::Tag *tag) const
{
	int r = -1;
	TagLib::ID3v2::FrameList l = tag->frameListMap()["POPM"];
	if (l.isEmpty()) {
		return r;
	}
	if (TagLib::ID3v2::PopularimeterFrame *pf = static_cast<TagLib::ID3v2::PopularimeterFrame*>(l.front())) {
		switch (pf->rating()) {
		case 1:
			r = 1;
			break;
		case 64:
			r = 2;
			break;
		case 128:
			r = 3;
			break;
		case 196:
			r = 4;
			break;
		case 255:
			r = 5;
			break;
		}
	}
	return r;
}
Ejemplo n.º 5
0
bool CTagBase::exportImage(const wchar_t* s)
{
	if (!s)	return false;
	if (_tagFile)
	{
		//get picture
		TagLib::MPEG::File *f = (TagLib::MPEG::File *)_tagFile.get();
		if (!f->hasID3v2Tag() || f->ID3v2Tag()->isEmpty())
			return false;
		/*
		TagLib::ID3v2::FrameList::ConstIterator it = f->ID3v2Tag()->frameList().begin();
		for (; it != f->ID3v2Tag()->frameList().end(); it++)
		{
			if ((*it)->frameID().operator == (TagLib::ByteVector("APIC")))
			{
				HANDLE hFile = CreateFile(s, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
				if (INVALID_HANDLE_VALUE == hFile)
					return false;
				int nWriteBytes = 0;
				size_t size = (*it)->size();
				::WriteFile(hFile, (*it)->render().data(), (*it)->size(), (LPDWORD)&nWriteBytes, NULL);
				::CloseHandle(hFile);
				if (nWriteBytes != size)
					return false;
				return true;
			}
		}*/
		if (f->ID3v2Tag()->frameListMap().size() == 0)
			return false;
		if (f->ID3v2Tag()->frameListMap().find("APIC") == f->ID3v2Tag()->frameListMap().end())
			return false;

		TagLib::ID3v2::FrameList Flist = f->ID3v2Tag()->frameListMap()["APIC"];
		if (Flist.isEmpty())
			return false;
		TagLib::ID3v2::AttachedPictureFrame *p = static_cast<TagLib::ID3v2::AttachedPictureFrame *>(Flist.front());
		size_t size = p->picture().size();
		CString strPicType = p->mimeType().toCString(true);
		int nPos = strPicType.Find('/');
		CString strTemp = strPicType.Right(strPicType.GetLength() - nPos - 1);
		//CString strPicPath   = s;

		//if (strTemp == _T("png"))
		//	strPicPath.Append(_T(".png"));
		//else
		//	strPicPath.Append(_T(".jpg"));

		HANDLE hFile = CreateFile(s, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
		if (INVALID_HANDLE_VALUE == hFile)
			return false;
		int nWriteBytes = 0;
		::WriteFile(hFile, p->picture().data(), size, (LPDWORD)&nWriteBytes, NULL);
		::CloseHandle(hFile);
		if (nWriteBytes != size)
			return false;

		return true;
	}
	return false;
}
Ejemplo n.º 6
0
void FileHelper::setFlacAttribute(const std::string &attribute, const QString &value)
{
	if (TagLib::FLAC::File *flacFile = static_cast<TagLib::FLAC::File*>(_file)) {
		if (flacFile->hasID3v2Tag()) {
			TagLib::ID3v2::Tag *tag = flacFile->ID3v2Tag();
			QString key = this->convertKeyToID3v2Key(attribute.data());
			TagLib::ID3v2::FrameList l = tag->frameListMap()[key.toStdString().data()];
			if (!l.isEmpty()) {
				tag->removeFrame(l.front());
			}
			TagLib::ID3v2::TextIdentificationFrame *tif = new TagLib::ID3v2::TextIdentificationFrame(TagLib::ByteVector("ARTISTALBUM"));
			tif->setText(value.toStdString().data());
			tag->addFrame(tif);
		} else if (flacFile->hasID3v1Tag()) {
			qDebug() << Q_FUNC_INFO << "Not implemented (FLAC ID3v1)";
		} else if (flacFile->hasXiphComment()) {
			TagLib::Ogg::XiphComment *xiph = flacFile->xiphComment();
			if (value.isEmpty()) {
				xiph->removeField(attribute.data());
			} else {
				xiph->addField(attribute.data(), value.toStdString().data());
			}
		}
	}
}
Ejemplo n.º 7
0
void loadCover(Tune *tune, TagLib::File *file)
{
	if (!searchLocalCover(tune)) {
		auto mpeg = dynamic_cast<TagLib::MPEG::File*>(file);

		if(mpeg) {
			TagLib::ID3v2::Tag* tag2 = mpeg->ID3v2Tag();
			if(tag2) {
				TagLib::ID3v2::FrameList frameList = tag2->frameList("APIC");
				if(!frameList.isEmpty()) {
					for(unsigned int i = 0; i < frameList.size(); ++i) {
						auto *coverImg = dynamic_cast<TagLib::ID3v2::AttachedPictureFrame *>(frameList[i]);
						if(coverImg) {
							QImage cover;
							if(cover.loadFromData(reinterpret_cast<const uchar*>(coverImg->picture().data()),
									      coverImg->picture().size()))
							{
								tune->setCover(cover);
								break;
							}
						}
					}
				}
			}
		}
	}
}
Ejemplo n.º 8
0
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;
}
Ejemplo n.º 9
0
void AudioTagger::addID3v2Tag(TagLib::ID3v2::Tag* id3v2) {
    if (!id3v2)
        return;

    TagLib::ID3v2::FrameList bpmFrame = id3v2->frameListMap()["TBPM"];
    if (!bpmFrame.isEmpty()) {
        bpmFrame.front()->setText(m_bpm.toStdString());
    } else {
         // add new frame TextIdentificationFrame which is responsible for TKEY and TBPM
         // see http://developer.kde.org/~wheeler/taglib/api/classTagLib_1_1ID3v2_1_1TextIdentificationFrame.html

        TagLib::ID3v2::TextIdentificationFrame* newFrame = new TagLib::ID3v2::TextIdentificationFrame("TBPM", TagLib::String::Latin1);

        newFrame->setText(m_bpm.toStdString());
        id3v2->addFrame(newFrame);

    }

    TagLib::ID3v2::FrameList keyFrame = id3v2->frameListMap()["TKEY"];
    if (!keyFrame.isEmpty()) {
        keyFrame.front()->setText(m_key.toStdString());
    } else {
        //add new frame
        TagLib::ID3v2::TextIdentificationFrame* newFrame = new TagLib::ID3v2::TextIdentificationFrame("TKEY", TagLib::String::Latin1);

        newFrame->setText(m_key.toStdString());
        id3v2->addFrame(newFrame);

    }

    TagLib::ID3v2::FrameList composerFrame = id3v2->frameListMap()["TCOM"];
    if (!composerFrame.isEmpty()) {
        composerFrame.front()->setText(m_composer.toStdString());
    } else {
        //add new frame
        TagLib::ID3v2::TextIdentificationFrame* newFrame =
                new TagLib::ID3v2::TextIdentificationFrame(
                    "TCOM", TagLib::String::Latin1);
        newFrame->setText(m_composer.toStdString());
        id3v2->addFrame(newFrame);
    }
}
Ejemplo n.º 10
0
QString FileHelper::extractMpegFeature(const QString &featureToExtract) const
{
	QString feature;
	if (TagLib::MPEG::File *mpegFile = static_cast<TagLib::MPEG::File*>(_file)) {
		if (mpegFile->hasID3v2Tag()) {
			TagLib::ID3v2::FrameList l = mpegFile->ID3v2Tag()->frameListMap()[featureToExtract.toStdString().data()];
			if (!l.isEmpty()) {
				feature = QString(l.front()->toString().toCString(true));
			}
		}
	}
	return feature;
}
Ejemplo n.º 11
0
TagLib::Tag *mttFile::getTag( bool create )
{
    if ( tag == NULL ) {
		fileref = new TagLib::FileRef( QFile::encodeName( fname ).constData() );

        if ( fileref ) {
            if ( ismpeg ) {
                TagLib::MPEG::File *f = dynamic_cast<TagLib::MPEG::File *>(fileref->file());
                tag = new TagLib::ID3v2::Tag();
                if ( f->ID3v2Tag( create ) != NULL ) {
                    TagLib::Tag::duplicate( dynamic_cast<TagLib::Tag *>( f->ID3v2Tag( create ) ), tag, true );

                    // Read extra mp3 tags
                    int i;
                    for ( i = 0; i < EF_NUM; i++ ) {
                        TagLib::ID3v2::FrameList l = f->ID3v2Tag()->frameListMap()[extraFrames[i][0]];

                        if ( !l.isEmpty() ) {
                            mp3eframes += extraFrames[i][0];
                            mp3eframes += TStringToQString( l.front()->toString() );
                        }
                    }
                }


                delete fileref;
                fileref = NULL;
                return tag;
            }
            else { // If the file is ogg or flac
                tag = new TagLib::Ogg::XiphComment();
                if ( fileref->tag() ) // If a tag already exists
                    TagLib::Tag::duplicate( fileref->tag(), tag, true );
                delete fileref;
                fileref = NULL;
                return tag;
            }
        }
        else {
            //qDebug( "fileref = NULL" );
            return NULL;
        }

        delete fileref;
        fileref = NULL;
    }
    else
        return tag;
}
Ejemplo n.º 12
0
void FileHelper::setArtistAlbum(const QString &artistAlbum)
{
	switch (_fileType) {
	case EXT_FLAC: {
		this->setFlacAttribute("ALBUMARTIST", artistAlbum);
		break;
	}
	case EXT_MP4:{
		TagLib::StringList l;
		l.append(artistAlbum.toStdString().data());
		TagLib::MP4::Item item(l);
		this->setMp4Attribute("aART", item);
		break;
	}
	case EXT_MPC:
		//mpcFile = static_cast<MPC::File*>(f);
		qDebug() << Q_FUNC_INFO << "Not implemented for MPC";
		break;
	case EXT_MP3:{
		TagLib::MPEG::File *mpegFile = static_cast<TagLib::MPEG::File*>(_file);
		if (mpegFile->hasID3v2Tag()) {
			TagLib::ID3v2::Tag *tag = mpegFile->ID3v2Tag();
			QString convertedKey = this->convertKeyToID3v2Key("ARTISTALBUM");
			TagLib::ID3v2::FrameList l = tag->frameListMap()[convertedKey.toStdString().data()];
			if (!l.isEmpty()) {
				tag->removeFrame(l.front());
			}
			TagLib::ID3v2::TextIdentificationFrame *tif = new TagLib::ID3v2::TextIdentificationFrame(TagLib::ByteVector(convertedKey.toStdString().data()));
			tif->setText(artistAlbum.toStdString().data());
			tag->addFrame(tif);
		} else if (mpegFile->hasID3v1Tag()) {
			qDebug() << Q_FUNC_INFO << "Not implemented for ID3v1Tag";
		}
		break;
	}
	case EXT_OGG: {
		TagLib::Ogg::XiphComment *xiphComment = static_cast<TagLib::Ogg::XiphComment*>(_file->tag());
		if (xiphComment) {
			xiphComment->addField("ALBUMARTIST", artistAlbum.toStdString().data());
		} else {
			qDebug() << Q_FUNC_INFO << "Not implemented for this OGG file";
		}
		break;
	}
	default:
		qDebug() << Q_FUNC_INFO << "Not implemented for this type of file";
		break;
	}
}
Ejemplo n.º 13
0
QString extractMBIDFromFile(TagLib::MPEG::File *file)
{
	TagLib::ID3v2::Tag *tag = file->ID3v2Tag();
	TagLib::ID3v2::FrameList ufid = tag->frameListMap()["UFID"];
	if (!ufid.isEmpty()) {
		for (TagLib::ID3v2::FrameList::Iterator i = ufid.begin(); i != ufid.end(); i++) {
			TagLib::ID3v2::UniqueFileIdentifierFrame *frame = dynamic_cast<TagLib::ID3v2::UniqueFileIdentifierFrame *>(*i);
			if (frame && frame->owner() == "http://musicbrainz.org") {
				TagLib::ByteVector id = frame->identifier();
				return QString::fromAscii(id.data(), id.size());
			}
		}
	}
	return QString();
}
Ejemplo n.º 14
0
bool CoverUtils::coverFromMPEGTags(TagLib::ID3v2::Tag *tag, Album *album) {

    if (!tag) return false;

    TagLib::ID3v2::FrameList list = tag->frameList("APIC");
    if (list.isEmpty()) return false;

    TagLib::ID3v2::AttachedPictureFrame *frame =
            static_cast<TagLib::ID3v2::AttachedPictureFrame *>(list.front());
    if (!frame) return false;
    const int frameSize = frame->picture().size();
    if (frameSize <= 0) return false;

    QImage image;
    image.loadFromData((const uchar *) frame->picture().data(), frame->picture().size());
    if (!isAcceptableImage(image)) return false;

    return saveImage(image, album);
}
Ejemplo n.º 15
0
/*!
 * \copydoc MetaIO::write()
 */
bool MetaIOID3::write(Metadata* mdata)
{
    TagLib::MPEG::File *mpegfile = OpenFile(mdata->Filename());

    if (!mpegfile)
        return false;

    TagLib::ID3v2::Tag *tag = mpegfile->ID3v2Tag();

    if (!tag)
    {
        delete mpegfile;
        return false;
    }

    WriteGenericMetadata(tag, mdata);

    // MythTV rating and playcount, stored in POPM frame
    writeRating(tag, mdata->Rating());
    writePlayCount(tag, mdata->PlayCount());

    // MusicBrainz ID
    UserTextIdentificationFrame *musicbrainz = NULL;
    musicbrainz = find(tag, "MusicBrainz Album Artist Id");

    if (mdata->Compilation())
    {

        if (!musicbrainz)
        {
            musicbrainz = new UserTextIdentificationFrame(TagLib::String::UTF8);
            tag->addFrame(musicbrainz);
            musicbrainz->setDescription("MusicBrainz Album Artist Id");
        }

        musicbrainz->setText(MYTH_MUSICBRAINZ_ALBUMARTIST_UUID);
    }
    else if (musicbrainz)
        tag->removeFrame(musicbrainz);

    // Compilation Artist Frame (TPE4/2)
    if (!mdata->CompilationArtist().isEmpty())
    {
        TextIdentificationFrame *tpe4frame = NULL;
        TagLib::ID3v2::FrameList tpelist = tag->frameListMap()["TPE4"];
        if (!tpelist.isEmpty())
            tpe4frame = (TextIdentificationFrame *)tpelist.front();

        if (!tpe4frame)
        {
            tpe4frame = new TextIdentificationFrame(TagLib::ByteVector("TPE4"),
                                                    TagLib::String::UTF8);
                                                    tag->addFrame(tpe4frame);
        }
        tpe4frame->setText(QStringToTString(mdata->CompilationArtist()));


        TextIdentificationFrame *tpe2frame = NULL;
        tpelist = tag->frameListMap()["TPE2"];
        if (!tpelist.isEmpty())
            tpe2frame = (TextIdentificationFrame *)tpelist.front();

        if (!tpe2frame)
        {
            tpe2frame = new TextIdentificationFrame(TagLib::ByteVector("TPE2"),
                                                    TagLib::String::UTF8);
                                                    tag->addFrame(tpe2frame);
        }
        tpe2frame->setText(QStringToTString(mdata->CompilationArtist()));
    }

    bool result = mpegfile->save();

    delete mpegfile;

    return result;
}
Ejemplo n.º 16
0
/*!
 * \copydoc MetaIO::read()
 */
Metadata *MetaIOID3::read(QString filename)
{
    TagLib::MPEG::File *mpegfile = OpenFile(filename);

    if (!mpegfile)
        return NULL;

    TagLib::ID3v2::Tag *tag = mpegfile->ID3v2Tag();

    if (!tag)
    {
        delete mpegfile;
        return NULL;
    }

    // if there is no ID3v2 tag, try to read the ID3v1 tag and copy it to the ID3v2 tag structure
    if (tag->isEmpty())
    {
        TagLib::ID3v1::Tag *tag_v1 = mpegfile->ID3v1Tag();

        if (!tag_v1)
        {
            delete mpegfile;
            return NULL;
        }

        if (!tag_v1->isEmpty())
        {
            tag->setTitle(tag_v1->title());
            tag->setArtist(tag_v1->artist());
            tag->setAlbum(tag_v1->album());
            tag->setTrack(tag_v1->track());
            tag->setYear(tag_v1->year());
            tag->setGenre(tag_v1->genre());
        }
    }

    Metadata *metadata = new Metadata(filename);

    ReadGenericMetadata(tag, metadata);

    bool compilation = false;

    // Compilation Artist (TPE4 Remix) or fallback to (TPE2 Band)
    // N.B. The existance of a either frame is NOT an indication that this
    // is a compilation, but if it is then one of them will probably hold
    // the compilation artist.
    TextIdentificationFrame *tpeframe = NULL;
    TagLib::ID3v2::FrameList tpelist = tag->frameListMap()["TPE4"];
    if (tpelist.isEmpty() || tpelist.front()->toString().isEmpty())
        tpelist = tag->frameListMap()["TPE2"];
    if (!tpelist.isEmpty())
        tpeframe = (TextIdentificationFrame *)tpelist.front();

    if (tpeframe && !tpeframe->toString().isEmpty())
    {
        QString compilation_artist = TStringToQString(tpeframe->toString())
                                                                    .trimmed();
        metadata->setCompilationArtist(compilation_artist);
    }

    // MythTV rating and playcount, stored in POPM frame
    PopularimeterFrame *popm = findPOPM(tag, email);

    if (!popm)
    {
        if (!tag->frameListMap()["POPM"].isEmpty())
            popm = dynamic_cast<PopularimeterFrame *>
                                        (tag->frameListMap()["POPM"].front());
    }

    if (popm)
    {
        int rating = popm->rating();
        rating = static_cast<int>(((static_cast<float>(rating)/255.0)
                                                                * 10.0) + 0.5);
        metadata->setRating(rating);
        metadata->setPlaycount(popm->counter());
    }

    // Look for MusicBrainz Album+Artist ID in TXXX Frame
    UserTextIdentificationFrame *musicbrainz = find(tag,
                                            "MusicBrainz Album Artist Id");

    if (musicbrainz)
    {
        // If the MusicBrainz ID is the special "Various Artists" ID
        // then compilation is TRUE
        if (!compilation && !musicbrainz->fieldList().isEmpty())
            compilation = (MYTH_MUSICBRAINZ_ALBUMARTIST_UUID
            == TStringToQString(musicbrainz->fieldList().front()));
    }

    // TLEN - Ignored intentionally, some encoders write bad values
    // e.g. Lame under certain circumstances will always write a length of
    // 27 hours

    metadata->setCompilation(compilation);

    TagLib::FileRef *fileref = new TagLib::FileRef(mpegfile);
    metadata->setLength(getTrackLength(fileref));
    // FileRef takes ownership of mpegfile, and is responsible for it's
    // deletion. Messy.
    delete fileref;

    return metadata;
}
Ejemplo n.º 17
0
static Meta::ReplayGainTagMap readID3v2Tags( TagLib::ID3v2::Tag *tag )
{
    Meta::ReplayGainTagMap map;
    {   // ID3v2.4.0 native replay gain tag support (as written by Quod Libet, for example).
        TagLib::ID3v2::FrameList frames = tag->frameListMap()["RVA2"];
        frames.append(tag->frameListMap()["XRVA"]);
        if ( !frames.isEmpty() )
        {
            for ( unsigned int i = 0; i < frames.size(); ++i )
            {
                // we have to parse this frame ourselves
                // ID3v2 frame header is 10 bytes, so skip that
                TagLib::ByteVector data = frames[i]->render().mid( 10 );
                unsigned int offset = 0;
                QString desc( data.data() );
                offset += desc.count() + 1;
                unsigned int channel = data.mid( offset, 1 ).toUInt( true );
                // channel 1 is the main volume - the only one we care about
                if ( channel == 1 )
                {
                    ++offset;
                    qint16 adjustment512 = data.mid( offset, 2 ).toShort( true );
                    qreal adjustment = ( (qreal)adjustment512 ) / 512.0;
                    offset += 2;
                    unsigned int peakBits = data.mid( offset, 1 ).toUInt( true );
                    ++offset;
                    bool ok = false;
                    qreal peak = readRVA2PeakValue( data.mid( offset ), peakBits, &ok );
                    if ( ok )
                    {
                        if ( desc.toLower() == "album" )
                        {
                            map[Meta::ReplayGain_Album_Gain] = adjustment;
                            map[Meta::ReplayGain_Album_Peak] = peakToDecibels( peak );
                        }
                        else if ( desc.toLower() == "track" || !map.contains( Meta::ReplayGain_Track_Gain ) )
                        {
                            map[Meta::ReplayGain_Track_Gain] = adjustment;
                            map[Meta::ReplayGain_Track_Peak] = peakToDecibels( peak );
                        }
                    }
                }
            }
            if ( !map.isEmpty() )
                return map;
        }
    }

    {   // Foobar2000-style ID3v2.3.0 tags
        TagLib::ID3v2::FrameList frames = tag->frameListMap()["TXXX"];
        for ( TagLib::ID3v2::FrameList::Iterator it = frames.begin(); it != frames.end(); ++it ) {
            TagLib::ID3v2::UserTextIdentificationFrame* frame =
                dynamic_cast<TagLib::ID3v2::UserTextIdentificationFrame*>( *it );
            if ( frame && frame->fieldList().size() >= 2 )
            {
                QString desc = TStringToQString( frame->description() ).toLower();
                if ( desc == "replaygain_album_gain" )
                    maybeAddGain( frame->fieldList()[1], Meta::ReplayGain_Album_Gain, &map );
                if ( desc == "replaygain_album_peak" )
                    maybeAddPeak( frame->fieldList()[1], Meta::ReplayGain_Album_Peak, &map );
                if ( desc == "replaygain_track_gain" )
                    maybeAddGain( frame->fieldList()[1], Meta::ReplayGain_Track_Gain, &map );
                if ( desc == "replaygain_track_peak" )
                    maybeAddPeak( frame->fieldList()[1], Meta::ReplayGain_Track_Peak, &map );
            }
        }
    }
    return map;
}
Ejemplo n.º 18
0
//Adds dir & its contents to the library
void libraryDialog::addDir2Lib(QDir dir)
{
	dir.setFilter(QDir::Files | QDir::Dirs | QDir::NoSymLinks | QDir::NoDotAndDotDot);
	QDirIterator di(dir, QDirIterator::Subdirectories);	

	while(di.hasNext())
	{
		di.next();		
		QString fpath = di.filePath();
		QFileInfo f = di.fileInfo();
		if(isAudioFile(f))//Add this song to the database
		{
			wchar_t wname[250]; //TODO: Dynamic. Need to figure out wchar length from QStr length
			wname[fpath.toWCharArray(wname)] = 0;
			TagLib::FileName fname(wname);
			//We'll store tag information in these:
			QMap<QString, QString> stmap;
			QMap<QString, int> itmap;
			
			TagLib::File* file = NULL;
			//MP3 Means we can check for additional info in ID3v2 tags
			if(f.suffix() == "mp3")
			{				
				TagLib::MPEG::File* fr = new TagLib::MPEG::File(fname, true, TagLib::AudioProperties::ReadStyle::Fast);				
				if(fr->ID3v2Tag())
				{					
					//Somehow this means album artist / band. http://www.id3.org/id3v2.4.0-frames
					TagLib::ID3v2::FrameList l = fr->ID3v2Tag()->frameList("TPE2");
					if(!l.isEmpty())
						stmap["albumartist"] = l.front()->toString().toCString();
				}
				file = dynamic_cast<TagLib::File*>(fr);
			}
			if(file == NULL)
			{
				qDebug() << "ERR: " + fpath;
				continue; //TODO: Error out here
			}
			//Try to get audio properties
			TagLib::AudioProperties* ap = file->audioProperties();			
			
			TagLib::Tag* genTag = file->tag();			
			stmap["name"] = genTag->title().toCString();
			stmap["genre"] = genTag->genre().toCString();
			itmap["year"] = genTag->year();
			itmap["tracknum"] = genTag->track();
			stmap["album"] = genTag->album().toCString();						
			stmap["artist"] = genTag->artist().toCString();			
			if(ap != NULL)
				itmap["length"] = ap->length();
			stmap["path"] = fpath;	
			//Add collected info to db
			DBItem s;
			s.strVals = stmap;
			s.intVals = itmap;

			myparent->dbi->addSong(s);
			delete file;
		}
		else if(f.isDir())
			ui.curDirLbl->setText(fpath);
		//if(top) //If we're the top level of recursion update prog bar
		//	ui.progressBar->setValue(di./siz * 100);		
		qApp->processEvents();
	}
}
Ejemplo n.º 19
0
/*!
 * \copydoc MetaIO::read()
 */
Metadata *MetaIOID3::read(const QString &filename)
{
    if (!OpenFile(filename))
        return NULL;

    TagLib::ID3v2::Tag *tag = GetID3v2Tag(true); // Create tag if none are found

    // if there is no ID3v2 tag, try to read the ID3v1 tag and copy it to
    // the ID3v2 tag structure
    if (tag->isEmpty())
    {
        TagLib::ID3v1::Tag *tag_v1 = GetID3v1Tag();

        if (!tag_v1)
            return NULL;

        if (!tag_v1->isEmpty())
        {
            tag->setTitle(tag_v1->title());
            tag->setArtist(tag_v1->artist());
            tag->setAlbum(tag_v1->album());
            tag->setTrack(tag_v1->track());
            tag->setYear(tag_v1->year());
            tag->setGenre(tag_v1->genre());
        }
    }

    Metadata *metadata = new Metadata(filename);

    ReadGenericMetadata(tag, metadata);

    bool compilation = false;

    // Compilation Artist (TPE4 Remix) or fallback to (TPE2 Band)
    // N.B. The existance of a either frame is NOT an indication that this
    // is a compilation, but if it is then one of them will probably hold
    // the compilation artist.
    TextIdentificationFrame *tpeframe = NULL;
    TagLib::ID3v2::FrameList tpelist = tag->frameListMap()["TPE4"];
    if (tpelist.isEmpty() || tpelist.front()->toString().isEmpty())
        tpelist = tag->frameListMap()["TPE2"];
    if (!tpelist.isEmpty())
        tpeframe = (TextIdentificationFrame *)tpelist.front();

    if (tpeframe && !tpeframe->toString().isEmpty())
    {
        QString compilation_artist = TStringToQString(tpeframe->toString())
                                                                    .trimmed();
        metadata->setCompilationArtist(compilation_artist);
    }

    // MythTV rating and playcount, stored in POPM frame
    PopularimeterFrame *popm = findPOPM(tag, email);

    if (!popm)
    {
        if (!tag->frameListMap()["POPM"].isEmpty())
            popm = dynamic_cast<PopularimeterFrame *>
                                        (tag->frameListMap()["POPM"].front());
    }

    if (popm)
    {
        int rating = popm->rating();
        rating = static_cast<int>(((static_cast<float>(rating)/255.0)
                                                                * 10.0) + 0.5);
        metadata->setRating(rating);
        metadata->setPlaycount(popm->counter());
    }

    // Look for MusicBrainz Album+Artist ID in TXXX Frame
    UserTextIdentificationFrame *musicbrainz = find(tag,
                                            "MusicBrainz Album Artist Id");

    if (musicbrainz)
    {
        // If the MusicBrainz ID is the special "Various Artists" ID
        // then compilation is TRUE
        if (!compilation && !musicbrainz->fieldList().isEmpty())
            compilation = (MYTH_MUSICBRAINZ_ALBUMARTIST_UUID
            == TStringToQString(musicbrainz->fieldList().front()));
    }

    // TLEN - Ignored intentionally, some encoders write bad values
    // e.g. Lame under certain circumstances will always write a length of
    // 27 hours

    // Length
    if (!tag->frameListMap()["TLEN"].isEmpty())
    {
        int length = tag->frameListMap()["TLEN"].front()->toString().toInt();
        LOG(VB_FILE, LOG_DEBUG,
            QString("MetaIOID3::read: Length for '%1' from tag is '%2'\n").arg(filename).arg(length));
    }

    metadata->setCompilation(compilation);

    metadata->setLength(getTrackLength(m_file));

    // The number of tracks on the album, if supplied
    if (!tag->frameListMap()["TRCK"].isEmpty())
    {
        QString trackFrame = TStringToQString(
                                tag->frameListMap()["TRCK"].front()->toString())
                                    .trimmed();
        int trackCount = trackFrame.section('/', -1).toInt();
        if (trackCount > 0)
            metadata->setTrackCount(trackCount);
    }

    LOG(VB_FILE, LOG_DEBUG,
            QString("MetaIOID3::read: Length for '%1' from properties is '%2'\n").arg(filename).arg(metadata->Length()));

    return metadata;
}
Ejemplo n.º 20
0
/*!
 * \copydoc MetaIO::write()
 */
bool MetaIOID3::write(const QString &filename, MusicMetadata* mdata)
{
    if (filename.isEmpty())
        return false;

    if (!OpenFile(filename, true))
        return false;

    TagLib::ID3v2::Tag *tag = GetID3v2Tag();

    if (!tag)
        return false;

    WriteGenericMetadata(tag, mdata);

    // MythTV rating and playcount, stored in POPM frame
    writeRating(tag, mdata->Rating());
    writePlayCount(tag, mdata->PlayCount());
    writeLastPlay(tag, mdata->LastPlay());

    // MusicBrainz ID
    UserTextIdentificationFrame *musicbrainz = nullptr;
    musicbrainz = find(tag, "MusicBrainz Album Artist Id");

    if (mdata->Compilation())
    {

        if (!musicbrainz)
        {
            musicbrainz = new UserTextIdentificationFrame(TagLib::String::UTF8);
            tag->addFrame(musicbrainz);
            musicbrainz->setDescription("MusicBrainz Album Artist Id");
        }

        musicbrainz->setText(MYTH_MUSICBRAINZ_ALBUMARTIST_UUID);
    }
    else if (musicbrainz)
        tag->removeFrame(musicbrainz);

    // Compilation Artist Frame (TPE4/2)
    if (!mdata->CompilationArtist().isEmpty())
    {
        TextIdentificationFrame *tpe4frame = nullptr;
        TagLib::ID3v2::FrameList tpelist = tag->frameListMap()["TPE4"];
        if (!tpelist.isEmpty())
            tpe4frame = (TextIdentificationFrame *)tpelist.front();

        if (!tpe4frame)
        {
            tpe4frame = new TextIdentificationFrame(TagLib::ByteVector("TPE4"),
                                                    TagLib::String::UTF8);
            tag->addFrame(tpe4frame);
        }
        tpe4frame->setText(QStringToTString(mdata->CompilationArtist()));


        TextIdentificationFrame *tpe2frame = nullptr;
        tpelist = tag->frameListMap()["TPE2"];
        if (!tpelist.isEmpty())
            tpe2frame = (TextIdentificationFrame *)tpelist.front();

        if (!tpe2frame)
        {
            tpe2frame = new TextIdentificationFrame(TagLib::ByteVector("TPE2"),
                                                    TagLib::String::UTF8);
            tag->addFrame(tpe2frame);
        }
        tpe2frame->setText(QStringToTString(mdata->CompilationArtist()));
    }

    if (!SaveFile())
        return false;

    return true;
}
Ejemplo n.º 21
0
QString TagLibMetadata::getKey() 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()["TKEY"];
      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 Key tag");
      #else
        qDebug("ID3v1 does not support the Key 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()["TKEY"];
      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()["TKEY"];
      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){
    #ifdef Q_OS_WIN
      qDebug("iTunes metadata does not support the Key tag");
    #else
      qDebug("iTunes metadata does not support the Key tag (%s)",f->name());
    #endif
    return "N/A";
  }

  TagLib::ASF::Tag* tagTestAsf = dynamic_cast<TagLib::ASF::Tag*>(f->tag());
  if(tagTestAsf != NULL){
    TagLib::ASF::AttributeList l = tagTestAsf->attributeListMap()["WM/InitialKey"];
    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){
    #ifdef Q_OS_WIN
      qDebug("APE metadata does not support the Key tag");
    #else
      qDebug("APE metadata does not support the Key tag (%s)",f->name());
    #endif
    return "N/A";
  }

  #ifdef Q_OS_WIN
    qDebug("Key tag read failed all tests");
  #else
    qDebug("Key tag read failed all tests on %s",f->name());
  #endif

  return "N/A";
}
Ejemplo n.º 22
0
/*!
 * \copydoc MetaIO::read()
 */
MusicMetadata *MetaIOID3::read(const QString &filename)
{
    if (!OpenFile(filename))
        return nullptr;

    TagLib::ID3v2::Tag *tag = GetID3v2Tag(true); // Create tag if none are found

    // if there is no ID3v2 tag, try to read the ID3v1 tag and copy it to
    // the ID3v2 tag structure
    if (tag->isEmpty())
    {
        TagLib::ID3v1::Tag *tag_v1 = GetID3v1Tag();

        if (!tag_v1)
            return nullptr;

        if (!tag_v1->isEmpty())
        {
            tag->setTitle(tag_v1->title());
            tag->setArtist(tag_v1->artist());
            tag->setAlbum(tag_v1->album());
            tag->setTrack(tag_v1->track());
            tag->setYear(tag_v1->year());
            tag->setGenre(tag_v1->genre());
        }
    }

    MusicMetadata *metadata = new MusicMetadata(filename);

    ReadGenericMetadata(tag, metadata);

    bool compilation = false;

    // Compilation Artist (TPE4 Remix) or fallback to (TPE2 Band)
    // N.B. The existance of a either frame is NOT an indication that this
    // is a compilation, but if it is then one of them will probably hold
    // the compilation artist.
    TextIdentificationFrame *tpeframe = nullptr;
    TagLib::ID3v2::FrameList tpelist = tag->frameListMap()["TPE4"];
    if (tpelist.isEmpty() || tpelist.front()->toString().isEmpty())
        tpelist = tag->frameListMap()["TPE2"];
    if (!tpelist.isEmpty())
        tpeframe = (TextIdentificationFrame *)tpelist.front();

    if (tpeframe && !tpeframe->toString().isEmpty())
    {
        QString compilation_artist = TStringToQString(tpeframe->toString())
                                                                    .trimmed();
        metadata->setCompilationArtist(compilation_artist);
    }

    // Rating and playcount, stored in POPM frame
    PopularimeterFrame *popm = findPOPM(tag, ""); // Global (all apps) tag

    // If no 'global' tag exists, look for the MythTV specific one
    if (!popm)
    {
        popm = findPOPM(tag, email);
    }

    // Fallback to using any POPM tag we can find
    if (!popm)
    {
        if (!tag->frameListMap()["POPM"].isEmpty())
            popm = dynamic_cast<PopularimeterFrame *>
                                        (tag->frameListMap()["POPM"].front());
    }

    if (popm)
    {
        int rating = popm->rating();
        rating = lroundf(static_cast<float>(rating) / 255.0f * 10.0f);
        metadata->setRating(rating);
        metadata->setPlaycount(popm->counter());
    }

    // Look for MusicBrainz Album+Artist ID in TXXX Frame
    UserTextIdentificationFrame *musicbrainz = find(tag,
                                            "MusicBrainz Album Artist Id");

    if (musicbrainz)
    {
        // If the MusicBrainz ID is the special "Various Artists" ID
        // then compilation is TRUE
        if (!compilation && !musicbrainz->fieldList().isEmpty())
        {
            TagLib::StringList l = musicbrainz->fieldList();
            for (TagLib::StringList::ConstIterator it = l.begin(); it != l.end(); it++)
            {
                QString ID = TStringToQString((*it));

                if (ID == MYTH_MUSICBRAINZ_ALBUMARTIST_UUID)
                {
                    compilation = true;
                    break;
                }
            }
        }
    }

    // TLEN - Ignored intentionally, some encoders write bad values
    // e.g. Lame under certain circumstances will always write a length of
    // 27 hours

    // Length
    if (!tag->frameListMap()["TLEN"].isEmpty())
    {
        int length = tag->frameListMap()["TLEN"].front()->toString().toInt();
        LOG(VB_FILE, LOG_DEBUG,
            QString("MetaIOID3::read: Length for '%1' from tag is '%2'\n").arg(filename).arg(length));
    }

    metadata->setCompilation(compilation);

    metadata->setLength(getTrackLength(m_file));

    // The number of tracks on the album, if supplied
    if (!tag->frameListMap()["TRCK"].isEmpty())
    {
        QString trackFrame = TStringToQString(
                                tag->frameListMap()["TRCK"].front()->toString())
                                    .trimmed();
        int trackCount = trackFrame.section('/', -1).toInt();
        if (trackCount > 0)
            metadata->setTrackCount(trackCount);
    }

    LOG(VB_FILE, LOG_DEBUG,
            QString("MetaIOID3::read: Length for '%1' from properties is '%2'\n").arg(filename).arg(metadata->Length()));

    // Look for MythTVLastPlayed in TXXX Frame
    UserTextIdentificationFrame *lastplayed = find(tag, "MythTVLastPlayed");
    if (lastplayed)
    {
        QString lastPlayStr = TStringToQString(lastplayed->toString());
        metadata->setLastPlay(QDateTime::fromString(lastPlayStr, Qt::ISODate));
    }

    // Part of a set
    if (!tag->frameListMap()["TPOS"].isEmpty())
    {
        QString pos = TStringToQString(
                        tag->frameListMap()["TPOS"].front()->toString()).trimmed();

        int discNumber = pos.section('/', 0, 0).toInt();
        int discCount  = pos.section('/', -1).toInt();

        if (discNumber > 0)
            metadata->setDiscNumber(discNumber);
        if (discCount > 0)
            metadata->setDiscCount(discCount);
    }

    return metadata;
}
Ejemplo n.º 23
0
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";
}