ID3v2Tag::ID3v2Tag( TagLib::Tag *tag, TagLib::ID3v2::Tag *id3v2Tag ) : Tag( tag ) , m_id3v2Tag( id3v2Tag ) { TagLib::ID3v2::FrameList fList = m_id3v2Tag->frameList(); for( TagLib::ID3v2::FrameList::ConstIterator it = fList.begin(); it != fList.end(); ++it ) { TagLib::String frameId = TagLib::String( (*it)->frameID() ); TagLib::ID3v2::TextIdentificationFrame *frame = dynamic_cast< TagLib::ID3v2::TextIdentificationFrame * >( *it ); if( frame ) { QString val = TStringToQString( frame->fieldList().toString( '\n' ) ); if( frameId == TagLib::String( "TPE2" ) ) //album artist { m_albumArtist = val; } else if( frameId == TagLib::String( "TCOM" ) ) //composer { m_composer = val; } else if( frameId == TagLib::String( "TPOS" ) ) //disc number { m_discNumber = processDiscNumber( val ); } } } }
void FileHelper::setFlacAttribute(const std::string &attribute, const QString &value) { if (TagLib::FLAC::File *flacFile = static_cast<TagLib::FLAC::File*>(_file)) { if (flacFile->hasID3v2Tag()) { TagLib::ID3v2::Tag *tag = flacFile->ID3v2Tag(); QString key = this->convertKeyToID3v2Key(attribute.data()); TagLib::ID3v2::FrameList l = tag->frameListMap()[key.toStdString().data()]; if (!l.isEmpty()) { tag->removeFrame(l.front()); } TagLib::ID3v2::TextIdentificationFrame *tif = new TagLib::ID3v2::TextIdentificationFrame(TagLib::ByteVector("ARTISTALBUM")); tif->setText(value.toStdString().data()); tag->addFrame(tif); } else if (flacFile->hasID3v1Tag()) { qDebug() << Q_FUNC_INFO << "Not implemented (FLAC ID3v1)"; } else if (flacFile->hasXiphComment()) { TagLib::Ogg::XiphComment *xiph = flacFile->xiphComment(); if (value.isEmpty()) { xiph->removeField(attribute.data()); } else { xiph->addField(attribute.data(), value.toStdString().data()); } } } }
void TagReader::SetTextFrame(const char* id, const std::string& value, TagLib::ID3v2::Tag* tag) const { TagLib::ByteVector id_vector(id); QVector<TagLib::ByteVector> frames_buffer; // Store and clear existing frames while (tag->frameListMap().contains(id_vector) && tag->frameListMap()[id_vector].size() != 0) { frames_buffer.push_back(tag->frameListMap()[id_vector].front()->render()); tag->removeFrame(tag->frameListMap()[id_vector].front()); } // If no frames stored create empty frame if (frames_buffer.isEmpty()) { TagLib::ID3v2::TextIdentificationFrame frame(id_vector, TagLib::String::UTF8); frames_buffer.push_back(frame.render()); } // Update and add the frames for (int lyrics_index = 0; lyrics_index < frames_buffer.size(); lyrics_index++) { TagLib::ID3v2::TextIdentificationFrame* frame = new TagLib::ID3v2::TextIdentificationFrame( frames_buffer.at(lyrics_index)); if (lyrics_index == 0) { frame->setText(StdStringToTaglibString(value)); } // add frame takes ownership and clears the memory tag->addFrame(frame); } }
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; } }
void TagReader::SetTextFrame(const char* id, const std::string& value, TagLib::ID3v2::Tag* tag) const { TagLib::ByteVector id_vector(id); // Remove the frame if it already exists while (tag->frameListMap().contains(id_vector) && tag->frameListMap()[id_vector].size() != 0) { tag->removeFrame(tag->frameListMap()[id_vector].front()); } // Create and add a new frame TagLib::ID3v2::TextIdentificationFrame* frame = new TagLib::ID3v2::TextIdentificationFrame(id_vector, TagLib::String::UTF8); frame->setText(StdStringToTaglibString(value)); tag->addFrame(frame); }
/** * Set the file-type specific `compilation' tag. * * See the discussion on top of this file about which tag is used * for which file-type. * * @param file taggit's file-data structure for the processed file * @param tag the tag-data decoded by `taglib_file_tag()' * @param value the string the user wants to set this tag to * * @return void * @sideeffects none */ void taggit_tag_set_compilation(struct taggit_file *file, TagLib_Tag *tag, const char *value) { TagLib::APE::Tag *ape; TagLib::ID3v2::Tag *v2; TagLib::Ogg::XiphComment *ogg; const char *ret; TagLib::MPEG::File::File *f; int mask; ret = (const char *)NULL; switch (file->type) { case FT_MPEG: f = reinterpret_cast<TagLib::MPEG::File::File *>(file->data); mask = setup_get_write_mask(FT_MPEG); if (mask & MP3_ID3V2) { v2 = f->ID3v2Tag(); v2->removeFrames("TPE2"); /* * @TODO: I don't know how to figure out the proper `encoding' * value here. Should we look at the `unicodeStrings' * variable from taglib? */ TagLib::ID3v2::TextIdentificationFrame *frame = new TagLib::ID3v2::TextIdentificationFrame( "TPE2", TagLib::String::Latin1); frame->setText(value); v2->addFrame(frame); } if (mask & MP3_APE) { ape = f->APETag(); ape->addValue("ALBUMARTIST", value, true); } break; case FT_OGGVORBIS: /* @FALLTHROUGH@ */ case FT_OGGFLAC: ogg = reinterpret_cast<TagLib::Ogg::XiphComment *>(tag); ogg->addField("ALBUMARTIST", value, true); break; default: break; } }
/** 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; } }
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 AudioTagger::addID3v2Tag(TagLib::ID3v2::Tag* id3v2) { if (!id3v2) return; TagLib::ID3v2::FrameList bpmFrame = id3v2->frameListMap()["TBPM"]; if (!bpmFrame.isEmpty()) { bpmFrame.front()->setText(m_bpm.toStdString()); } else { // add new frame TextIdentificationFrame which is responsible for TKEY and TBPM // see http://developer.kde.org/~wheeler/taglib/api/classTagLib_1_1ID3v2_1_1TextIdentificationFrame.html TagLib::ID3v2::TextIdentificationFrame* newFrame = new TagLib::ID3v2::TextIdentificationFrame("TBPM", TagLib::String::Latin1); newFrame->setText(m_bpm.toStdString()); id3v2->addFrame(newFrame); } TagLib::ID3v2::FrameList keyFrame = id3v2->frameListMap()["TKEY"]; if (!keyFrame.isEmpty()) { keyFrame.front()->setText(m_key.toStdString()); } else { //add new frame TagLib::ID3v2::TextIdentificationFrame* newFrame = new TagLib::ID3v2::TextIdentificationFrame("TKEY", TagLib::String::Latin1); newFrame->setText(m_key.toStdString()); id3v2->addFrame(newFrame); } TagLib::ID3v2::FrameList composerFrame = id3v2->frameListMap()["TCOM"]; if (!composerFrame.isEmpty()) { composerFrame.front()->setText(m_composer.toStdString()); } else { //add new frame TagLib::ID3v2::TextIdentificationFrame* newFrame = new TagLib::ID3v2::TextIdentificationFrame( "TCOM", TagLib::String::Latin1); newFrame->setText(m_composer.toStdString()); id3v2->addFrame(newFrame); } }
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; }
Meta::FieldHash ID3v2TagHelper::tags() const { Meta::FieldHash data = TagHelper::tags(); TagLib::ID3v2::FrameList list = m_tag->frameList(); for( TagLib::ID3v2::FrameList::ConstIterator it = list.begin(); it != list.end(); ++it ) { qint64 field; TagLib::String frameName = TagLib::String( ( *it )->frameID() ); if( ( field = fieldName( frameName ) ) ) { if( field == Meta::valUniqueId ) { TagLib::ID3v2::UniqueFileIdentifierFrame *frame = dynamic_cast< TagLib::ID3v2::UniqueFileIdentifierFrame * >( *it ); if( !frame ) continue; QString identifier = TStringToQString( TagLib::String( frame->identifier() ) ); if( identifier.isEmpty() ) continue; if( frame->owner() == uidFieldName( UIDAFT ) && isValidUID( identifier, UIDAFT ) ) data.insert( Meta::valUniqueId, identifier ); continue; } else if( field == Meta::valHasCover ) { TagLib::ID3v2::AttachedPictureFrame *frame = dynamic_cast< TagLib::ID3v2::AttachedPictureFrame * >( *it ); if( !frame ) continue; if( ( frame->type() == TagLib::ID3v2::AttachedPictureFrame::FrontCover || frame->type() == TagLib::ID3v2::AttachedPictureFrame::Other ) && frame->picture().size() > MIN_COVER_SIZE ) // must be at least 1kb { data.insert( Meta::valHasCover, true ); } continue; } TagLib::ID3v2::TextIdentificationFrame *frame = dynamic_cast< TagLib::ID3v2::TextIdentificationFrame * >( *it ); if( !frame ) continue; QString value = TStringToQString( frame->fieldList().toString( '\n' ) ); if( field == Meta::valDiscNr ) { int disc; if( ( disc = splitDiscNr( value ).first ) ) data.insert( field, disc ); } else if( field == Meta::valBpm ) data.insert( field, value.toFloat() ); else data.insert( field, value ); } else if( frameName == POPM_Frame ) { TagLib::ID3v2::PopularimeterFrame *frame = dynamic_cast< TagLib::ID3v2::PopularimeterFrame * >( *it ); if( !frame ) continue; if( TStringToQString( frame->email() ).isEmpty() ) // only read anonymous ratings { // FMPS tags have precedence if( !data.contains( Meta::valRating ) && frame->rating() != 0 ) data.insert( Meta::valRating, qRound( frame->rating() / 256.0 * 10.0 ) ); if( !data.contains( Meta::valPlaycount ) && frame->counter() < 10000 ) data.insert( Meta::valPlaycount, frame->counter() ); } } else if( frameName == TXXX_Frame ) { TagLib::ID3v2::UserTextIdentificationFrame *frame = dynamic_cast< TagLib::ID3v2::UserTextIdentificationFrame * >( *it ); if( !frame ) continue; // the value of the user text frame is stored in the // second and following fields. TagLib::StringList fields = frame->fieldList(); if( fields.size() >= 2 ) { QString value = TStringToQString( fields[1] ); if( fields[0] == fmpsFieldName( FMPSRating ) ) data.insert( Meta::valRating, qRound( value.toFloat() * 10.0 ) ); else if( fields[0] == fmpsFieldName( FMPSScore ) ) data.insert( Meta::valScore, value.toFloat() * 100.0 ); else if( fields[0] == fmpsFieldName( FMPSPlayCount ) ) data.insert( Meta::valPlaycount, value.toFloat() ); } } } return data; }
bool ID3v2TagHelper::setTags( const Meta::FieldHash &changes ) { bool modified = TagHelper::setTags( changes ); foreach( const qint64 key, changes.keys() ) { QVariant value = changes.value( key ); TagLib::ByteVector field( fieldName( key ).toCString() ); if( !field.isNull() && !field.isEmpty() ) { if( key == Meta::valHasCover ) continue; else if( key == Meta::valUniqueId ) { QPair< UIDType, QString > uidPair = splitUID( value.toString() ); if( uidPair.first == UIDInvalid ) continue; TagLib::String owner = uidFieldName( uidPair.first ); TagLib::ByteVector uid( uidPair.second.toAscii().data() ); TagLib::ID3v2::FrameList list = m_tag->frameList(); for( TagLib::ID3v2::FrameList::ConstIterator it = list.begin(); it != list.end(); ++it ) { if( ( *it )->frameID() == field ) { TagLib::ID3v2::UniqueFileIdentifierFrame *frame = dynamic_cast< TagLib::ID3v2::UniqueFileIdentifierFrame * >( *it ); if( !frame ) continue; if( frame->owner() == owner ) { m_tag->removeFrame( frame ); modified = true; break; } } } if ( !uid.isEmpty() ) { m_tag->addFrame( new TagLib::ID3v2::UniqueFileIdentifierFrame( owner, uid ) ); modified = true; } continue; } TagLib::String tValue = Qt4QStringToTString( ( key == Meta::valCompilation ) ? QString::number( value.toInt() ) : value.toString() ); if( tValue.isEmpty() ) m_tag->removeFrames( field ); else { TagLib::ID3v2::TextIdentificationFrame *frame = NULL; if( !m_tag->frameListMap()[field].isEmpty() ) frame = dynamic_cast< TagLib::ID3v2::TextIdentificationFrame * >( m_tag->frameListMap()[field].front() ); if( !frame ) { frame = new TagLib::ID3v2::TextIdentificationFrame( field ); m_tag->addFrame( frame ); } // note: TagLib is smart enough to automatically set UTF8 encoding if needed. frame->setText( tValue ); } modified = true; } else if( key == Meta::valScore || key == Meta::valRating || key == Meta::valPlaycount ) { TagLib::String description; TagLib::String tValue; if( key == Meta::valRating ) { description = fmpsFieldName( FMPSRating ); tValue = Qt4QStringToTString( QString::number( value.toFloat() / 10.0 ) ); } else if( key == Meta::valScore ) { description = fmpsFieldName( FMPSScore ); tValue = Qt4QStringToTString( QString::number( value.toFloat() / 100.0 ) ); } else if( key == Meta::valPlaycount ) { description = fmpsFieldName( FMPSPlayCount ); tValue = Qt4QStringToTString( QString::number( value.toInt() ) ); } if( key == Meta::valRating || key == Meta::valPlaycount ) { TagLib::ID3v2::PopularimeterFrame *popFrame = NULL; if( !m_tag->frameListMap()[POPM_Frame].isEmpty() ) popFrame = dynamic_cast< TagLib::ID3v2::PopularimeterFrame * >( m_tag->frameListMap()[POPM_Frame].front() ); if( !popFrame ) { popFrame = new TagLib::ID3v2::PopularimeterFrame( POPM_Frame ); m_tag->addFrame( popFrame ); } if( key == Meta::valRating ) popFrame->setRating( qBound(0, int(qRound(value.toDouble() / 10.0 * 256)), 255) ); else popFrame->setCounter( value.toInt() ); modified = true; } TagLib::ID3v2::FrameList list = m_tag->frameList(); for( TagLib::ID3v2::FrameList::ConstIterator it = list.begin(); it != list.end(); ++it ) { if( ( *it )->frameID() == TXXX_Frame ) { TagLib::ID3v2::UserTextIdentificationFrame *frame = dynamic_cast< TagLib::ID3v2::UserTextIdentificationFrame * >( *it ); if( !frame ) continue; if( frame->description() == description ) { m_tag->removeFrame( frame ); modified = true; break; } } } if( value.toBool() ) { TagLib::ID3v2::UserTextIdentificationFrame *frame = new TagLib::ID3v2::UserTextIdentificationFrame( TXXX_Frame ); frame->setDescription( description ); frame->setText( tValue ); m_tag->addFrame( frame ); modified = true; } } } return modified; }