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; }
/*! * \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; }
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; }
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; }
/** 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; }
/** 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(); }
/** 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; }
/** 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; } }
/** 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; } }
/*! * \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; }
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(); } }
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 ) ); }
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; }
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; } }
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; }
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(); }
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; }
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; }
/*! * \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; }
/*! * \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; }
/*! * \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; }
//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(); } }
/*! * \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; }
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; }
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; }
/* 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; }
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)
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; }
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(); }
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; }