예제 #1
0
파일: tagBase.cpp 프로젝트: hjhong/MyDuiLib
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;
}
예제 #2
0
/*!
 * \brief Read the albumart image from the file
 *
 * \param filename The filename for which we want to find the length.
 * \param type The type of image we want - front/back etc
 * \returns A pointer to a QImage owned by the caller or NULL if not found.
 */
QImage* MetaIOID3::getAlbumArt(QString filename, ImageType type)
{
    QImage *picture = new QImage();

    AttachedPictureFrame::Type apicType
        = AttachedPictureFrame::FrontCover;

    switch (type)
    {
        case IT_UNKNOWN :
            apicType = AttachedPictureFrame::Other;
            break;
        case IT_FRONTCOVER :
            apicType = AttachedPictureFrame::FrontCover;
            break;
        case IT_BACKCOVER :
            apicType = AttachedPictureFrame::BackCover;
            break;
        case IT_CD :
            apicType = AttachedPictureFrame::Media;
            break;
        case IT_INLAY :
            apicType = AttachedPictureFrame::LeafletPage;
            break;
        default:
            return picture;
    }

    QByteArray fname = filename.toLocal8Bit();
    TagLib::MPEG::File *mpegfile = new TagLib::MPEG::File(fname.constData());

    if (mpegfile)
    {
        if (mpegfile->isOpen()
            && !mpegfile->ID3v2Tag()->frameListMap()["APIC"].isEmpty())
        {
            TagLib::ID3v2::FrameList apicframes =
                                    mpegfile->ID3v2Tag()->frameListMap()["APIC"];

            for(TagLib::ID3v2::FrameList::Iterator it = apicframes.begin();
                it != apicframes.end(); ++it)
            {
                AttachedPictureFrame *frame =
                                    static_cast<AttachedPictureFrame *>(*it);
                if (frame && frame->type() == apicType)
                {
                    picture->loadFromData((const uchar *)frame->picture().data(),
                                          frame->picture().size());
                    return picture;
                }
            }
        }

        delete mpegfile;
    }

    delete picture;

    return NULL;
}
예제 #3
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;
}
예제 #4
0
bool MetaIOID3::writeVolatileMetadata(const Metadata* mdata)
{
    QString filename = mdata->Filename();
    int rating = mdata->Rating();
    int playcount = mdata->PlayCount();
    TagLib::MPEG::File *mpegfile = OpenFile(filename);

    if (!mpegfile)
        return false;

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

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

    bool result = (writeRating(tag, rating) && writePlayCount(tag, playcount));

    mpegfile->save();
    delete mpegfile;

    return result;
}
예제 #5
0
/** Check if file has an inner picture. */
bool FileHelper::hasCover() const
{
	bool atLeastOnePicture = false;
	switch (_fileType) {
	case EXT_MP3: {
		TagLib::MPEG::File *mpegFile = static_cast<TagLib::MPEG::File*>(_file);
		if (mpegFile && mpegFile->hasID3v2Tag()) {
			// Look for picture frames only
			TagLib::ID3v2::FrameList listOfMp3Frames = mpegFile->ID3v2Tag()->frameListMap()["APIC"];
			// It's possible to have more than one picture per file!
			if (!listOfMp3Frames.isEmpty()) {
				for (TagLib::ID3v2::FrameList::ConstIterator it = listOfMp3Frames.begin(); it != listOfMp3Frames.end() ; it++) {
					// Cast a Frame* to AttachedPictureFrame*
					TagLib::ID3v2::AttachedPictureFrame *pictureFrame = static_cast<TagLib::ID3v2::AttachedPictureFrame*>(*it);
					atLeastOnePicture = atLeastOnePicture || (pictureFrame != nullptr && !pictureFrame->picture().isEmpty());
				}
			}
		}
		break;
	}
	case EXT_FLAC: {
		if (TagLib::FLAC::File *flacFile = static_cast<TagLib::FLAC::File*>(_file)) {
			atLeastOnePicture = !flacFile->pictureList().isEmpty();
		}
	}
	default:
		break;
	}
	return atLeastOnePicture;
}
예제 #6
0
/** Set or remove any rating. */
void FileHelper::setRating(int rating)
{
	switch (_fileType) {
	case EXT_MP3: {
		TagLib::MPEG::File *mpegFile = static_cast<TagLib::MPEG::File*>(_file);
		if (mpegFile->hasID3v2Tag()) {
			this->setRatingForID3v2(rating, mpegFile->ID3v2Tag());
		} else if (mpegFile->hasID3v1Tag()) {
			qDebug() << Q_FUNC_INFO << "Not implemented for ID3v1Tag";
		}
		break;
	}
	case EXT_FLAC: {
		TagLib::FLAC::File *flacFile = static_cast<TagLib::FLAC::File*>(_file);
		if (flacFile->hasID3v2Tag()) {
			this->setRatingForID3v2(rating, flacFile->ID3v2Tag());
		} else if (flacFile->hasID3v1Tag()) {
			qDebug() << Q_FUNC_INFO << "hasID3v1Tag";
		} else if (flacFile->hasXiphComment()) {
			TagLib::Ogg::XiphComment *xiph = flacFile->xiphComment();
			if (rating == 0) {
				xiph->removeField("RATING");
			} else {
				xiph->addField("RATING", QString::number(rating).toStdString());
			}
		}
		break;
	}
	default:
		break;
	}
	this->save();
}
예제 #7
0
/** 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;
}
예제 #8
0
/** Sets the inner picture. */
void FileHelper::setCover(Cover *cover)
{
	switch (_fileType) {
	case EXT_MP3: {
		TagLib::MPEG::File *mpegFile = static_cast<TagLib::MPEG::File*>(_file);
		if (mpegFile->hasID3v2Tag()) {
			// Look for picture frames only
			TagLib::ID3v2::FrameList mp3Frames = mpegFile->ID3v2Tag()->frameListMap()["APIC"];
			if (!mp3Frames.isEmpty()) {
				for (TagLib::ID3v2::FrameList::Iterator it = mp3Frames.begin(); it != mp3Frames.end() ; it++) {
					// Removing a frame will invalidate any pointers on the list
					mpegFile->ID3v2Tag()->removeFrame(*it);
					break;
				}
			}
			if (cover != nullptr) {
				TagLib::ByteVector bv(cover->byteArray().data(), cover->byteArray().length());
				TagLib::ID3v2::AttachedPictureFrame *pictureFrame = new TagLib::ID3v2::AttachedPictureFrame();
				pictureFrame->setMimeType(cover->mimeType());
				pictureFrame->setPicture(bv);
				pictureFrame->setType(TagLib::ID3v2::AttachedPictureFrame::FrontCover);
				mpegFile->ID3v2Tag()->addFrame(pictureFrame);
			}
		} else if (mpegFile->hasID3v1Tag()) {
			qDebug() << Q_FUNC_INFO << "Not implemented for ID3v1Tag";
		}
		break;
	}
	case EXT_FLAC: {
		TagLib::FLAC::File *flacFile = static_cast<TagLib::FLAC::File*>(_file);
		flacFile->removePictures();
		if (cover != nullptr) {
			TagLib::FLAC::Picture *picture = new TagLib::FLAC::Picture;
			picture->setType(TagLib::FLAC::Picture::FrontCover);
			TagLib::ByteVector bv(cover->byteArray().data(), cover->byteArray().length());
			picture->setData(bv);
			flacFile->addPicture(picture);
		}
		break;
	}
	default:
		qDebug() << Q_FUNC_INFO << "Not implemented for" << _fileType;
		break;
	}
}
예제 #9
0
/** Set or remove any disc number. */
void FileHelper::setDiscNumber(const QString &disc)
{
	switch (_fileType) {
	case EXT_FLAC: {
		this->setFlacAttribute("DISCNUMBER", disc);
		break;
	}
	case EXT_OGG: {
		TagLib::Ogg::XiphComment *xiphComment = static_cast<TagLib::Ogg::XiphComment*>(_file->tag());
		if (xiphComment) {
			xiphComment->addField("DISCNUMBER", disc.toStdString().data());
		} else {
			qDebug() << Q_FUNC_INFO << "Not implemented for this OGG file";
		}
		break;
	}
	case EXT_MP3: {
		TagLib::MPEG::File *mpegFile = static_cast<TagLib::MPEG::File*>(_file);
		if (mpegFile && mpegFile->hasID3v2Tag()) {
			// Remove existing disc number if one has set an empty string
			if (disc.isEmpty()) {
				mpegFile->ID3v2Tag()->removeFrames(TagLib::ByteVector("TPOS"));
			} else {
				TagLib::ID3v2::TextIdentificationFrame *f = new TagLib::ID3v2::TextIdentificationFrame(TagLib::ByteVector("TPOS"));
				f->setText(disc.toStdString());
				mpegFile->ID3v2Tag()->addFrame(f);
			}
		}
		break;
	}
	case EXT_MP4: {
		TagLib::MP4::Item item(disc.toUInt());
		this->setMp4Attribute("disk", item);
		break;
	}
	default:
		qDebug() << Q_FUNC_INFO << "Not implemented for this file type";
		break;
	}
}
예제 #10
0
/*!
 * \brief Remove the albumart image from the file
 *
 * \param filename The music file to remove the albumart
 * \param albumart The Album Art image to remove
 * \returns True if successful
 */
bool MetaIOID3::removeAlbumArt(const QString &filename, const AlbumArtImage *albumart)
{
    if (filename.isEmpty() || !albumart)
        return false;

    AttachedPictureFrame::Type type = AttachedPictureFrame::Other;
    switch (albumart->imageType)
    {
        case IT_FRONTCOVER:
            type = AttachedPictureFrame::FrontCover;
            break;
        case IT_BACKCOVER:
            type = AttachedPictureFrame::BackCover;
            break;
        case IT_CD:
            type = AttachedPictureFrame::Media;
            break;
        case IT_INLAY:
            type = AttachedPictureFrame::LeafletPage;
            break;
        default:
            type = AttachedPictureFrame::Other;
            break;
    }

    TagLib::MPEG::File *mpegfile = OpenFile(filename);

    if (!mpegfile)
        return false;

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

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

    AttachedPictureFrame *apic = findAPIC(tag, type, QStringToTString(albumart->description));
    if (!apic)
    {
        delete mpegfile;
        return false;
    }

    tag->removeFrame(apic);

    mpegfile->save();
    delete mpegfile;

    return true;
}
예제 #11
0
bool mttFile::saveTag( void )
{
    fileref = new TagLib::FileRef( QFile::encodeName( fname ).constData() );

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

        // Remove id3v1 tag. Help put that hack into eternal rest :-)
        f->strip( TagLib::MPEG::File::ID3v1, true );
        //qDebug("ID3v1 tag stripped!");

        TagLib::Tag::duplicate( tag, dynamic_cast<TagLib::Tag *>( f->ID3v2Tag( true ) ), true );

        // Save extra mp3 tags
        TagLib::ID3v2::TextIdentificationFrame *myframe;
        TagLib::ID3v2::Tag *mytag;

        mytag = f->ID3v2Tag( false );
        for ( QStringList::Iterator it = mp3eframes.begin(); it != mp3eframes.end(); ++it ) {
            myframe = new TagLib::ID3v2::TextIdentificationFrame( (*it).toAscii().constData(), TagLib::String::UTF8 );
            mytag->removeFrames( (*it).toAscii().constData() );
            ++it;
            myframe->setText( Q4StringToTString( (*it) ) );
            mytag->addFrame( myframe );
        }

        
	delete fileref;
	fileref = NULL;
	return f->save( TagLib::MPEG::File::ID3v2, true );
    }
    else {
        TagLib::Tag::duplicate( tag, fileref->tag(), true );
	delete fileref;
	fileref = NULL;
        return fileref->save();
    }

}
예제 #12
0
void
MetaBundle::readTags( TagLib::AudioProperties::ReadStyle readStyle )
{
    if( m_url.protocol() != "file" )
        return;

    const QString path = m_url.path();
    TagLib::FileRef fileref;
    TagLib::Tag *tag = 0;

    if( AmarokConfig::recodeID3v1Tags() && path.endsWith( ".mp3", false ) )
    {
        TagLib::MPEG::File *mpeg = new TagLib::MPEG::File( QFile::encodeName( path ), true, readStyle );
        fileref = TagLib::FileRef( mpeg );

        if( mpeg->isValid() )
            // we prefer ID3v1 over ID3v2 if recoding tags because
            // apparently this is what people who ignore ID3 standards want
            tag = mpeg->ID3v1Tag() ? (TagLib::Tag*)mpeg->ID3v1Tag() : (TagLib::Tag*)mpeg->ID3v2Tag();
    }

    else {
        fileref = TagLib::FileRef( QFile::encodeName( path ), true, readStyle );

        if( !fileref.isNull() )
            tag = fileref.tag();
    }

    if( !fileref.isNull() ) {
        if ( tag ) {
            #define strip( x ) TStringToQString( x ).stripWhiteSpace()
            m_title   = strip( tag->title() );
            m_artist  = strip( tag->artist() );
            m_album   = strip( tag->album() );
            m_comment = strip( tag->comment() );
            m_genre   = strip( tag->genre() );
            m_year    = tag->year() ? QString::number( tag->year() ) : QString();
            m_track   = tag->track() ? QString::number( tag->track() ) : QString();
            #undef strip

            m_isValidMedia = true;
        }

        init( fileref.audioProperties() );
    }

    //FIXME disabled for beta4 as it's simpler to not got 100 bug reports
    //else if( KMimeType::findByUrl( m_url )->is( "audio" ) )
    //    init( KFileMetaInfo( m_url, QString::null, KFileMetaInfo::Everything ) );
}
예제 #13
0
bool FileHelper::save()
{
	if (_fileType == EXT_MP3) {
		TagLib::MPEG::File *mpegFile = static_cast<TagLib::MPEG::File*>(_file);
		// TagLib updates tags with the latest version (ID3v2.4)
		// We just want to save the file with the exact same version!
		if (mpegFile->hasID3v2Tag()) {
			return mpegFile->save(TagLib::MPEG::File::AllTags, false, mpegFile->ID3v2Tag()->header()->majorVersion());
		}
	} else if (_fileType != EXT_UNKNOWN) {
		return _file->save();
	}
	return false;
}
예제 #14
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;
	}
}
예제 #15
0
bool CCover::GetComposer(TagLib::FileRef& fr, std::string& composer)
{
    TagLib::MPEG::File        * mpgfile   = NULL;
    TagLib::Ogg::Vorbis::File * oggfile   = NULL;
    TagLib::FLAC::File        * flacfile  = NULL;
    TagLib::Ogg::XiphComment  * xiph      = NULL;
    TagLib::ID3v2::Tag        * id3v2     = NULL;
#ifdef TAGLIB_HAVE_MP4
    TagLib::MP4::File         * mp4file   = NULL;
    TagLib::MP4::Tag          * mp4       = NULL;
#endif

    if ((oggfile = dynamic_cast<TagLib::Ogg::Vorbis::File*>(fr.file()))) {
        xiph=oggfile->tag();
        //log_debug("ogg");
    } else if ((flacfile = dynamic_cast<TagLib::FLAC::File*>(fr.file()))) {
        xiph=flacfile->xiphComment();
        id3v2=flacfile->ID3v2Tag();
        //log_debug("flac");
    } else if ((mpgfile = dynamic_cast<TagLib::MPEG::File*>(fr.file()))) {
        id3v2=mpgfile->ID3v2Tag();
        //log_debug("mpg");
    }
#ifdef TAGLIB_HAVE_MP4
    else if ((mp4file = dynamic_cast<TagLib::MP4::File*>(fr.file()))) {
        mp4=mp4file->tag();
    }
#endif
#ifndef TAGLIB_HAVE_MP4
    void* mp4 = NULL;
#endif
    //log_debug4("xiph=%p, id3v2=%p, mp4=%p", xiph, id3v2, mp4);

    bool retval = true;
    if (xiph)
        retval = xiph_get_field(xiph, "COMPOSER",composer);
    else if (id3v2)
        retval = id3v2_get_field(id3v2, "TCOM",composer);
#ifdef TAGLIB_HAVE_MP4
    else if (mp4)
        retval = mp4_get_field(mp4file, "\251wrt",composer);
#endif
    else
        retval = false;

    //log_debug2("composer = %s", composer.c_str());

    return retval;
}
예제 #16
0
파일: tagBase.cpp 프로젝트: hjhong/MyDuiLib
bool CTagBase::addImage(wchar_t* s)
{
	if (!_tagFile) return false;
	TagLib::MPEG::File *pAudioFile = (TagLib::MPEG::File *)_tagFile.get();
	CString strFileName = s;
	ImageFile imageFile((CW2A)strFileName.GetBuffer());
	if (!pAudioFile->isValid() || !imageFile.isValid())
		return false;
	TagLib::ID3v2::Tag *tag = pAudioFile->ID3v2Tag(true);
	TagLib::ID3v2::AttachedPictureFrame *frame = new TagLib::ID3v2::AttachedPictureFrame;
	frame->setMimeType(imageFile.mimeType());
	frame->setPicture(imageFile.data());
	tag->addFrame(frame);
	return pAudioFile->save();

}
예제 #17
0
Cover* FileHelper::extractCover()
{
	Cover *cover = nullptr;
	switch (_fileType) {
	case EXT_MP3: {
		TagLib::MPEG::File *mpegFile = static_cast<TagLib::MPEG::File*>(_file);
		if (mpegFile && mpegFile->hasID3v2Tag()) {
			// Look for picture frames only
			TagLib::ID3v2::FrameList listOfMp3Frames = mpegFile->ID3v2Tag()->frameListMap()["APIC"];
			// It's possible to have more than one picture per file!
			if (!listOfMp3Frames.isEmpty()) {
				for (TagLib::ID3v2::FrameList::ConstIterator it = listOfMp3Frames.begin(); it != listOfMp3Frames.end() ; it++) {
					// Cast a Frame* to AttachedPictureFrame*
					TagLib::ID3v2::AttachedPictureFrame *pictureFrame = static_cast<TagLib::ID3v2::AttachedPictureFrame*>(*it);
					if (pictureFrame) {
						// Performs a deep copy of the cover
						QByteArray b = QByteArray(pictureFrame->picture().data(), pictureFrame->picture().size());
						cover = new Cover(b, QString(pictureFrame->mimeType().toCString(true)));
					}
				}
			}
		} else if (mpegFile && mpegFile->hasID3v1Tag()) {
			qDebug() << Q_FUNC_INFO << "Not implemented for ID3v1Tag";
		}
		break;
	}
	case EXT_FLAC: {
		if (TagLib::FLAC::File *flacFile = static_cast<TagLib::FLAC::File*>(_file)) {
			auto list = flacFile->pictureList();
			for (auto it = list.begin(); it != list.end() ; it++) {
				TagLib::FLAC::Picture *p = *it;
				if (p->type() == TagLib::FLAC::Picture::FrontCover) {
					// Performs a deep copy of the cover
					QByteArray b = QByteArray(p->data().data(), p->data().size());
					cover = new Cover(b, QString(p->mimeType().toCString(true)));
					break;
				}
			}
		}
		break;
	}
	default:
		qDebug() << Q_FUNC_INFO << "Not implemented for this file type" << _fileType << _file << _fileInfo.absoluteFilePath();
		break;
	}
	return cover;
}
예제 #18
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;
}
예제 #19
0
/*!
 * \brief Read the albumart images from the file
 *
 * \param filename The filename for which we want to find the images.
 */
AlbumArtList MetaIOID3::getAlbumArtList(const QString &filename)
{
    AlbumArtList imageList;
    QByteArray fname = filename.toLocal8Bit();
    TagLib::MPEG::File *mpegfile = new TagLib::MPEG::File(fname.constData());

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

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

        imageList = readAlbumArt(tag);

        delete mpegfile;
    }

    return imageList;
}
예제 #20
0
/*!
 * \brief Write the albumart image to the file
 *
 * \param filename The music file to add the albumart
 * \param albumart The Album Art image to write
 * \returns True if successful
 *
 * \Note We always save the image in JPEG format
 */
bool MetaIOID3::writeAlbumArt(const QString &filename, const AlbumArtImage *albumart)
{
    if (filename.isEmpty() || !albumart)
        return false;

    // load the image into a QByteArray
    QImage image(albumart->filename);
    QByteArray imageData;
    QBuffer buffer(&imageData);
    buffer.open(QIODevice::WriteOnly);
    image.save(&buffer, "JPEG");

    AttachedPictureFrame::Type type = AttachedPictureFrame::Other;
    switch (albumart->imageType)
    {
        case IT_FRONTCOVER:
            type = AttachedPictureFrame::FrontCover;
            break;
        case IT_BACKCOVER:
            type = AttachedPictureFrame::BackCover;
            break;
        case IT_CD:
            type = AttachedPictureFrame::Media;
            break;
        case IT_INLAY:
            type = AttachedPictureFrame::LeafletPage;
            break;
        default:
            type = AttachedPictureFrame::Other;
            break;
    }

    TagLib::MPEG::File *mpegfile = OpenFile(filename);

    if (!mpegfile)
        return false;

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

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

    AttachedPictureFrame *apic = findAPIC(tag, type, QStringToTString(albumart->description));

    if (!apic)
    {
        apic = new AttachedPictureFrame();
        tag->addFrame(apic);
        apic->setType(type);
    }

    QString mimetype = "image/jpeg";

    TagLib::ByteVector bytevector;
    bytevector.setData(imageData.data(), imageData.size());

    apic->setMimeType(QStringToTString(mimetype));
    apic->setPicture(bytevector);
    apic->setDescription(QStringToTString(albumart->description));

    mpegfile->save();
    delete mpegfile;

    return true;
}
예제 #21
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;
}
예제 #22
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();
	}
}
예제 #23
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;
}
예제 #24
0
void LocalSong::setInfo(const QString &filePath)
{
    QFileInfo fileInfo(filePath);
    fileExtension = fileInfo.completeSuffix();
    QString singer="";
    QString sname="";
    QString album="";
    QImage covpic;
    if(fileExtension == "m4a")
    {

        TagLib::MP4::File *mp4File = new TagLib::MP4::File(
                    QFile::encodeName(filePath).constData());
        if(false==mp4File->isOpen())
            return;
        sname=QString(mp4File->tag()->title().toCString(true));
        singer=QString(mp4File->tag()->artist().toCString(true));
        album=QString(mp4File->tag()->album().toCString(true));
        TagLib::MP4::ItemListMap itemListMap = mp4File->tag()->itemListMap();
        TagLib::MP4::Item albumArtItem = itemListMap["covr"];
        TagLib::MP4::CoverArtList albumArtList = albumArtItem.toCoverArtList();
        TagLib::MP4::CoverArt albumArt = albumArtList.front();
        QImage cover;
        cover.loadFromData((const uchar *)
                           albumArt.data().data(),
                           albumArt.data().size());
        covpic = cover.scaled(
                    50,
                    50,
                    Qt::IgnoreAspectRatio,
                    Qt::SmoothTransformation);
        if(!covpic.isNull())
        {
            qDebug()<<"读取M4A封面信息成功";
        }else
        {
            covpic.load(":/image/image/playIcon.png");
            qDebug()<<"读取音乐封面信息失败";
        }
    }
    else if(fileExtension == "mp3")
    {
        TagLib::MPEG::File *mpegFile = new TagLib::MPEG::File(
                    QFile::encodeName(filePath).constData());
        if(false==mpegFile->isOpen())
            return;
        else
        {
            sname=QString(mpegFile->tag()->title().toCString(true));
            singer=QString(mpegFile->tag()->artist().toCString(true));
            album=QString(mpegFile->tag()->album().toCString(true));
            auto tag = mpegFile->ID3v2Tag(false);
            auto list = tag->frameListMap()["APIC"];
            if(!list.isEmpty()) {
                auto frame = list.front();
                auto pic = reinterpret_cast<TagLib::ID3v2::AttachedPictureFrame *>(frame);
                if(pic && !pic->picture().isNull())
                {
                    QImage cover;
                    if(cover.loadFromData(QByteArray::fromRawData(pic->picture().data(), pic->picture().size()))) {
                        covpic = cover.scaled(
                                    50,
                                    50,
                                    Qt::IgnoreAspectRatio,
                                    Qt::SmoothTransformation);
                        qDebug()<<"读取MP3封面信息成功";
                    }
                }
            }
            else
            {
                covpic.load(":/image/image/playIcon.png");
                qDebug()<<"读取音乐封面信息失败";
            }
        }
    }
    singerlist.append(singer);
    snamelist.append(sname);
    albumlist.append(album);
    covPiclist.append(covpic);
    int covCount=covPiclist.length();
    QString covpicpath=QDir::tempPath()+QString("/%1.png").arg(covCount);
    covpic.save(covpicpath);
    QUrl covpicUrl=QUrl::fromLocalFile(covpicpath);
    qDebug()<<"歌名为"<<sname;
    qDebug()<<"歌手为"<<singer;
    qDebug()<<"专辑为"<<album;
    qDebug()<<"URL为"<<covpicUrl;
    emit setSongInfo(singer,sname,album,covpicUrl);
    return;
}
예제 #25
0
bool CTagLoaderTagLib::Load(const string& strFileName, CMusicInfoTag& tag, EmbeddedArt *art /* = NULL */)
{  
  CStdString strExtension;
  URIUtils::GetExtension(strFileName, strExtension);
  strExtension.ToLower();
  strExtension.TrimLeft('.');

  if (strExtension.IsEmpty())
    return false;

  TagLibVFSStream*           stream = new TagLibVFSStream(strFileName, true);
  if (!stream)
  {
    CLog::Log(LOGERROR, "could not create TagLib VFS stream for: %s", strFileName.c_str());
    return false;
  }
  
  TagLib::File*              file = NULL;
  TagLib::APE::File*         apeFile = NULL;
  TagLib::ASF::File*         asfFile = NULL;
  TagLib::FLAC::File*        flacFile = NULL;
  TagLib::IT::File*          itFile = NULL;
  TagLib::Mod::File*         modFile = NULL;
  TagLib::MP4::File*         mp4File = NULL;
  TagLib::MPC::File*         mpcFile = NULL;
  TagLib::MPEG::File*        mpegFile = NULL;
  TagLib::Ogg::Vorbis::File* oggVorbisFile = NULL;
  TagLib::Ogg::FLAC::File*   oggFlacFile = NULL;
  TagLib::S3M::File*         s3mFile = NULL;
  TagLib::TrueAudio::File*   ttaFile = NULL;
  TagLib::WavPack::File*     wvFile = NULL;
  TagLib::XM::File*          xmFile = NULL;

  if (strExtension == "ape")
    file = apeFile = new APE::File(stream);
  else if (strExtension == "asf" || strExtension == "wmv" || strExtension == "wma")
    file = asfFile = new ASF::File(stream);
  else if (strExtension == "flac")
    file = flacFile = new FLAC::File(stream, ID3v2::FrameFactory::instance());
  else if (strExtension == "it")
    file = itFile = new IT::File(stream);
  else if (strExtension == "mod" || strExtension == "module" || strExtension == "nst" || strExtension == "wow")
    file = modFile = new Mod::File(stream);
  else if (strExtension == "mp4" || strExtension == "m4a" || 
           strExtension == "m4r" || strExtension == "m4b" || 
           strExtension == "m4p" || strExtension == "3g2")
    file = mp4File = new MP4::File(stream);
  else if (strExtension == "mpc")
    file = mpcFile = new MPC::File(stream);
  else if (strExtension == "mp3" || strExtension == "aac")
    file = mpegFile = new MPEG::File(stream, ID3v2::FrameFactory::instance());
  else if (strExtension == "s3m")
    file = s3mFile = new S3M::File(stream);
  else if (strExtension == "tta")
    file = ttaFile = new TrueAudio::File(stream, ID3v2::FrameFactory::instance());
  else if (strExtension == "wv")
    file = wvFile = new WavPack::File(stream);
  else if (strExtension == "xm")
    file = xmFile = new XM::File(stream);
  else if (strExtension == "ogg")
    file = oggVorbisFile = new Ogg::Vorbis::File(stream);
  else if (strExtension == "oga") // Leave this madness until last - oga container can have Vorbis or FLAC
  {
    file = oggFlacFile = new Ogg::FLAC::File(stream);
    if (!file || !file->isValid())
    {
      delete file;
      file = oggVorbisFile = new Ogg::Vorbis::File(stream);
    }
  }

  if (!file || !file->isOpen())
  {
    delete file;
    delete stream;
    CLog::Log(LOGDEBUG, "file could not be opened for tag reading");
    return false;
  }

  APE::Tag *ape = NULL;
  ASF::Tag *asf = NULL;
  MP4::Tag *mp4 = NULL;
  ID3v2::Tag *id3v2 = NULL;
  Ogg::XiphComment *xiph = NULL;
  Tag *generic = NULL;

  if (apeFile)
    ape = apeFile->APETag(false);
  else if (asfFile)
    asf = asfFile->tag();
  else if (flacFile)
  {
    xiph = flacFile->xiphComment(false);
    id3v2 = flacFile->ID3v2Tag(false);
  }
  else if (mp4File)
    mp4 = mp4File->tag();
  else if (mpegFile)
  {
    id3v2 = mpegFile->ID3v2Tag(false);
    ape = mpegFile->APETag(false);
  }
  else if (oggFlacFile)
    xiph = dynamic_cast<Ogg::XiphComment *>(oggFlacFile->tag());
  else if (oggVorbisFile)
    xiph = dynamic_cast<Ogg::XiphComment *>(oggVorbisFile->tag());
  else if (ttaFile)
    id3v2 = ttaFile->ID3v2Tag(false);
  else if (wvFile)
    ape = wvFile->APETag(false);
  else    // This is a catch all to get generic information for other files types (s3m, xm, it, mod, etc)
    generic = file->tag();

  if (file->audioProperties())
    tag.SetDuration(file->audioProperties()->length());

  if (ape && !g_advancedSettings.m_prioritiseAPEv2tags)
    ParseAPETag(ape, art, tag);

  if (asf)
    ParseASF(asf, art, tag);
  else if (id3v2)
    ParseID3v2Tag(id3v2, art, tag);
  else if (generic)
    ParseGenericTag(generic, art, tag);
  else if (mp4)
    ParseMP4Tag(mp4, art, tag);
  else if (xiph)
    ParseXiphComment(xiph, art, tag);

  // art for flac files is outside the tag
  if (flacFile)
    SetFlacArt(flacFile, art, tag);

  // Add APE tags over the top of ID3 tags if we want to prioritize them
  if (ape && g_advancedSettings.m_prioritiseAPEv2tags)
    ParseAPETag(ape, art, tag);

  if (!tag.GetTitle().IsEmpty() || !tag.GetArtist().empty() || !tag.GetAlbum().IsEmpty())
    tag.SetLoaded();
  tag.SetURL(strFileName);

  delete file;
  delete stream;
  
  return true;
}
예제 #26
0
/* LOAD UP THE FILE'S TAG
 * Search each file type individually so we can get individual tags for
 * custom tagging.
 */
TagDatac * tag_data_load (char *url, int *pvalid)
{
    TagData * data;
    TagLib::String s = url;
    int mtime;
    struct stat buf;
    if (!stat (url, &buf))
        mtime = (int) buf.st_mtime;


   /* FIXME: Using filename to find media type. GStreamer probe instead?
   */
    if(s.size() > 4) {
        if(s.substr(s.size() - 4, 4).upper() == ".OGG")
        {
            TagLib::Vorbis::File * f = new TagLib::Vorbis::File(url);
            if (! f->isValid ())
                return NULL;
            data = (TagData*) malloc (sizeof (TagData));
            data->file = new TagLib::FileRef (f);
            data->id3v2 = NULL;
            data->id3v1 = NULL;
            data->ape   = NULL;
            data->xiph  = f->tag ();
            data->mime  = "application/ogg";
            data->mtime = mtime;
            return reinterpret_cast<TagDatac *> (data);
        }
        if(s.substr(s.size() - 4, 4).upper() == ".MP3")
        {
            TagLib::MPEG::File * f = new TagLib::MPEG::File(url);
            if (! f->isValid ())
                return NULL;
            data = (TagData*) malloc (sizeof (TagData));
            data->file = new TagLib::FileRef (f);
            data->id3v2 = f->ID3v2Tag ();
            data->id3v1 = f->ID3v1Tag ();
            data->ape   = f->APETag ();
            data->xiph  = NULL;
            data->mime  = "audio/mpeg";
            data->mtime = mtime;
            return reinterpret_cast<TagDatac *>(data);
        }
        if(s.substr(s.size() - 5, 5).upper() == ".FLAC")
        {
            TagLib::FLAC::File * f = new TagLib::FLAC::File(url);
            if ((! f->isValid ())&& (pvalid != NULL)){
				*pvalid = -1;//paul add on 080827 merge from Olive
                return NULL;
			}
            data = (TagData*) malloc (sizeof (TagData));
            data->file = new TagLib::FileRef (f);
            data->id3v2 = f->ID3v2Tag ();
            data->id3v1 = f->ID3v1Tag ();
            data->ape   = NULL;
            data->xiph  = f->xiphComment ();
            data->mime  = "audio/x-flac";
            data->mtime = mtime;
            return reinterpret_cast<TagDatac *>(data);
        }
        if(s.substr(s.size() - 4, 4).upper() == ".MPC" || s.substr(s.size() - 4, 4).upper() == ".AAC")
        {
            TagLib::MPC::File * f = new TagLib::MPC::File(url);
            if (! f->isValid ())
                return NULL;
            data = (TagData*) malloc (sizeof (TagData));
            data->file = new TagLib::FileRef (f);
            data->id3v2 = NULL;
            data->id3v1 = f->ID3v1Tag ();
            data->ape   = f->APETag ();
            data->xiph  = NULL;
            data->mime  = "audio/x-musepack";
            data->mtime = mtime;
            return reinterpret_cast<TagDatac *>(data);
        }
    }
    return NULL;
}
예제 #27
0
bool CTagLoaderTagLib::Load(const std::string& strFileName, CMusicInfoTag& tag, const std::string& fallbackFileExtension, MUSIC_INFO::EmbeddedArt *art /* = NULL */)
{
  std::string strExtension = URIUtils::GetExtension(strFileName);
  StringUtils::TrimLeft(strExtension, ".");

  if (strExtension.empty())
  {
    strExtension = fallbackFileExtension;
    if (strExtension.empty())
      return false;
  }

  StringUtils::ToLower(strExtension);
  TagLibVFSStream*           stream = new TagLibVFSStream(strFileName, true);
  if (!stream)
  {
    CLog::Log(LOGERROR, "could not create TagLib VFS stream for: %s", strFileName.c_str());
    return false;
  }

  ID3v1::Tag::setStringHandler(&ID3v1StringHandler);
  ID3v2::Tag::setLatin1StringHandler(&ID3v2StringHandler);
  TagLib::File*              file = NULL;
  TagLib::APE::File*         apeFile = NULL;
  TagLib::ASF::File*         asfFile = NULL;
  TagLib::FLAC::File*        flacFile = NULL;
  TagLib::IT::File*          itFile = NULL;
  TagLib::Mod::File*         modFile = NULL;
  TagLib::MP4::File*         mp4File = NULL;
  TagLib::MPC::File*         mpcFile = NULL;
  TagLib::MPEG::File*        mpegFile = NULL;
  TagLib::Ogg::Vorbis::File* oggVorbisFile = NULL;
  TagLib::Ogg::FLAC::File*   oggFlacFile = NULL;
  TagLib::S3M::File*         s3mFile = NULL;
  TagLib::TrueAudio::File*   ttaFile = NULL;
  TagLib::WavPack::File*     wvFile = NULL;
  TagLib::XM::File*          xmFile = NULL;
  TagLib::RIFF::WAV::File *  wavFile = NULL;
  TagLib::RIFF::AIFF::File * aiffFile = NULL;

  if (strExtension == "ape")
    file = apeFile = new APE::File(stream);
  else if (strExtension == "asf" || strExtension == "wmv" || strExtension == "wma")
    file = asfFile = new ASF::File(stream);
  else if (strExtension == "flac")
    file = flacFile = new FLAC::File(stream, ID3v2::FrameFactory::instance());
  else if (strExtension == "it")
    file = itFile = new IT::File(stream);
  else if (strExtension == "mod" || strExtension == "module" || strExtension == "nst" || strExtension == "wow")
    file = modFile = new Mod::File(stream);
  else if (strExtension == "mp4" || strExtension == "m4a" ||
           strExtension == "m4r" || strExtension == "m4b" ||
           strExtension == "m4p" || strExtension == "3g2")
    file = mp4File = new MP4::File(stream);
  else if (strExtension == "mpc")
    file = mpcFile = new MPC::File(stream);
  else if (strExtension == "mp3" || strExtension == "aac")
    file = mpegFile = new MPEG::File(stream, ID3v2::FrameFactory::instance());
  else if (strExtension == "s3m")
    file = s3mFile = new S3M::File(stream);
  else if (strExtension == "tta")
    file = ttaFile = new TrueAudio::File(stream, ID3v2::FrameFactory::instance());
  else if (strExtension == "wv")
    file = wvFile = new WavPack::File(stream);
  else if (strExtension == "aif" || strExtension == "aiff")
    file = aiffFile = new RIFF::AIFF::File(stream);
  else if (strExtension == "wav")
    file = wavFile = new RIFF::WAV::File(stream);
  else if (strExtension == "xm")
    file = xmFile = new XM::File(stream);
  else if (strExtension == "ogg")
    file = oggVorbisFile = new Ogg::Vorbis::File(stream);
  else if (strExtension == "oga") // Leave this madness until last - oga container can have Vorbis or FLAC
  {
    file = oggFlacFile = new Ogg::FLAC::File(stream);
    if (!file || !file->isValid())
    {
      delete file;
      oggFlacFile = NULL;
      file = oggVorbisFile = new Ogg::Vorbis::File(stream);
    }
  }

  if (!file || !file->isOpen())
  {
    delete file;
    delete stream;
    CLog::Log(LOGDEBUG, "file could not be opened for tag reading");
    return false;
  }

  APE::Tag *ape = NULL;
  ASF::Tag *asf = NULL;
  MP4::Tag *mp4 = NULL;
  ID3v1::Tag *id3v1 = NULL;
  ID3v2::Tag *id3v2 = NULL;
  Ogg::XiphComment *xiph = NULL;
  Tag *generic = NULL;

  if (apeFile)
    ape = apeFile->APETag(false);
  else if (asfFile)
    asf = asfFile->tag();
  else if (flacFile)
  {
    xiph = flacFile->xiphComment(false);
    id3v2 = flacFile->ID3v2Tag(false);
  }
  else if (mp4File)
    mp4 = mp4File->tag();
  else if (mpegFile)
  {
    id3v1 = mpegFile->ID3v1Tag(false);
    id3v2 = mpegFile->ID3v2Tag(false);
    ape = mpegFile->APETag(false);
  }
  else if (oggFlacFile)
    xiph = dynamic_cast<Ogg::XiphComment *>(oggFlacFile->tag());
  else if (oggVorbisFile)
    xiph = dynamic_cast<Ogg::XiphComment *>(oggVorbisFile->tag());
  else if (ttaFile)
    id3v2 = ttaFile->ID3v2Tag(false);
  else if (aiffFile)
    id3v2 = aiffFile->tag();
  else if (wavFile)
#if TAGLIB_MAJOR_VERSION > 1 || TAGLIB_MINOR_VERSION > 8
    id3v2 = wavFile->ID3v2Tag();
#else
    id3v2 = wavFile->tag();
#endif
  else if (wvFile)
예제 #28
0
bool mttFile::Open( QString filename )
{
    bool changed = false;

    fname = filename;

    fileref = new TagLib::FileRef( QFile::encodeName( filename ).constData() );
    if ( filename.endsWith( QString( ".mp3" ), Qt::CaseInsensitive ) ) {
        ismpeg = true;
        TagLib::MPEG::File *f = dynamic_cast<TagLib::MPEG::File *>(fileref->file());
        if ( f ) {
            if ( f->ID3v1Tag() ) {
                if ( !(f->ID3v2Tag()) ) {
					qDebug("ID3v1 found");
                    // Copy id3v1 tag to id3v2 tag
                    TagLib::ID3v1::Tag *v1tag = f->ID3v1Tag();
                    TagLib::ID3v2::Tag *v2tag = f->ID3v2Tag( true );
    
                    v2tag->setAlbum( v1tag->album() );
                    v2tag->setArtist( v1tag->artist() );
                    v2tag->setComment( v1tag->comment() );
                    v2tag->setGenre( v1tag->genre() );
                    v2tag->setTitle( v1tag->title() );
                    v2tag->setTrack( v1tag->track() );
                    v2tag->setYear( v1tag->year() );
                    changed = true;
                }
                else if ( f->ID3v2Tag() && f->ID3v1Tag() ) {
					qDebug("ID3v1 & v2 found");
                    // Fill gaps of ID3v2Tag from ID3v1Tag
                    TagLib::ID3v1::Tag *v1tag = f->ID3v1Tag();
                    TagLib::ID3v2::Tag *v2tag = f->ID3v2Tag();
    
                    if ( v2tag->album().isEmpty() ) {
                        v2tag->setAlbum( v1tag->album() );
                        changed = true;
                    }
                    if ( v2tag->artist().isEmpty() ) {
                        v2tag->setArtist( v1tag->artist() );
                        changed = true;
                    }
                    if ( v2tag->comment().isEmpty() ) {
                        v2tag->setComment( v1tag->comment() );
                        changed = true;
                    }
                    if ( v2tag->genre().isEmpty() ) {
                        v2tag->setGenre( v1tag->genre() );
                        changed = true;
                    }
                    if ( v2tag->title().isEmpty() ) {
                        v2tag->setTitle( v1tag->title() );
                        changed = true;
                    }
                    if ( v2tag->track() == 0 ) {
                        v2tag->setTrack( v1tag->track() );
                        changed = true;
                    }
                    if ( v2tag->year() == 0 ) {
                        v2tag->setYear( v1tag->year() );
                        changed = true;
                    }
                }
            }
        }
    }
    else if ( filename.endsWith( QString( ".ogg" ), Qt::CaseInsensitive ) ) {
        isogg = true;
    }
    else if ( filename.endsWith( QString( ".flac" ), Qt::CaseInsensitive ) ) {
        isflac = true;
    }

    delete fileref;
    fileref = NULL;

    return changed;
}
예제 #29
0
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();
}
예제 #30
0
int TagLibMetadata::setKey(const QString& key){

  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("TKEY");
      frm->setText(TagLib::String(key.toUtf8().data()));
      tagTestId3v2->removeFrames("TKEY");
      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 Key tag");
        #else
          qDebug("ID3v1 does not support the Key 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("TKEY");
      frm->setText(TagLib::String(key.toUtf8().data()));
      tagTestId3v2->removeFrames("TKEY");
      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("TKEY");
      frm->setText(TagLib::String(key.toUtf8().data()));
      tagTestId3v2->removeFrames("TKEY");
      tagTestId3v2->addFrame(frm);
      f->save();
      return 0;
    }
  }

  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 1;
  }

  TagLib::ASF::Tag* tagTestAsf = dynamic_cast<TagLib::ASF::Tag*>(f->tag());
  if(tagTestAsf != NULL){
    tagTestAsf->setAttribute("WM/InitialKey",TagLib::String(key.toUtf8().data()));
    f->save();
    return 0;
  }

  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 1;
  }

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