示例#1
0
void FileHelper::setFlacAttribute(const std::string &attribute, const QString &value)
{
	if (TagLib::FLAC::File *flacFile = static_cast<TagLib::FLAC::File*>(_file)) {
		if (flacFile->hasID3v2Tag()) {
			TagLib::ID3v2::Tag *tag = flacFile->ID3v2Tag();
			QString key = this->convertKeyToID3v2Key(attribute.data());
			TagLib::ID3v2::FrameList l = tag->frameListMap()[key.toStdString().data()];
			if (!l.isEmpty()) {
				tag->removeFrame(l.front());
			}
			TagLib::ID3v2::TextIdentificationFrame *tif = new TagLib::ID3v2::TextIdentificationFrame(TagLib::ByteVector("ARTISTALBUM"));
			tif->setText(value.toStdString().data());
			tag->addFrame(tif);
		} else if (flacFile->hasID3v1Tag()) {
			qDebug() << Q_FUNC_INFO << "Not implemented (FLAC ID3v1)";
		} else if (flacFile->hasXiphComment()) {
			TagLib::Ogg::XiphComment *xiph = flacFile->xiphComment();
			if (value.isEmpty()) {
				xiph->removeField(attribute.data());
			} else {
				xiph->addField(attribute.data(), value.toStdString().data());
			}
		}
	}
}
示例#2
0
unsigned TagWriter::Write(const std::string& filename, 
			  const db::Recordset *tags)
{
    util::Mutex::Lock lock(s_taglib_mutex);

//    TRACE << "Opening '" << filename << "'\n";
	    
    typedef std::map<std::string, std::string> tagmap_t;
    tagmap_t tagmap;
    for (unsigned int i=0; i<mediadb::FIELD_COUNT; ++i)
    {
	const char *s = import::GetVorbisTagForField(i);
	if (s)
	{
	    std::string val = tags->GetString(i);
	    if (!val.empty())
		tagmap[s] = val;
	}
    }

    TagLib::FLAC::File tff(filename.c_str());
    TagLib::Ogg::XiphComment *oxc = tff.xiphComment(true);
    for (tagmap_t::const_iterator i = tagmap.begin(); i != tagmap.end(); ++i)
    {
	if (!i->second.empty())
	    oxc->addField(i->first, TagLib::String(i->second, 
						   TagLib::String::UTF8));
    }
    tff.save();
    TRACE << "FLAC file tagged\n";
    return 0;
}
示例#3
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();
}
示例#4
0
文件: taglib_ext.cpp 项目: pft/taggit
/**
 * Get the various artist information form a tag.
 *
 * @param filetype the type-id for the file that is being processed
 * @param tagtype  the tag-type to use (if more than one are used per filetype)
 * @param tag      the tag-data from taglib
 *
 * @return      a proper multi-artist data field or a NULL pointer.
 * @sideeffects none
 */
const char *
taggit_tag_va(enum file_type filetype, int tagtype, TagLib_Tag *tag)
{
    /*
     * At this point, we already figured out the file type *and* decided which
     * tag to read from the file. `filetype' and `tagtype' give us hints into
     * the right direction. We *must* follow these hints or things will blow
     * up.
     */
    TagLib::APE::Tag *ape;
    TagLib::ID3v2::Tag *v2;
    TagLib::Ogg::XiphComment *ogg;
    const char *ret;

    ret = (const char *)NULL;
    switch (filetype) {
    case FT_MPEG:
        if (tagtype & MP3_ID3V2) {
            /**
             * @TODO Add support for TCMP (and maybe TCP) frames.
             * It's probably best to only check for those if TPE2 is empty,
             * because otherwise we already consider the track part of a
             * compilation.
             */
            v2 = reinterpret_cast<TagLib::ID3v2::Tag *>(tag);
            if (v2->frameListMap()["TPE2"].isEmpty())
                break;
            ret = xstrdup(
                v2->frameListMap()["TPE2"].front()->toString().toCString());
        } else if (tagtype & MP3_APE) {
            ape = reinterpret_cast<TagLib::APE::Tag *>(tag);
            if (ape->itemListMap()["ALBUMARTIST"].isEmpty())
                break;
            ret = xstrdup(
                ape->itemListMap()["ALBUMARTIST"].toString().toCString());
        }
        /* Don't care about ID3v1 */
        break;
    case FT_OGGVORBIS:
        /* @FALLTHROUGH@ */
    case FT_OGGFLAC:
        /* ogg* files share the same tag format */
        ogg = reinterpret_cast<TagLib::Ogg::XiphComment *>(tag);
        if (ogg->fieldListMap()["ALBUMARTIST"].isEmpty())
            break;
        ret = xstrdup(
            ogg->fieldListMap()["ALBUMARTIST"].toString().toCString());
        break;
    case FT_FLAC:
        /* AFAIK, there is no native FLAC tag format */
        break;
    default:
        break;
    }
    return ret;
}
示例#5
0
/*!
 * \copydoc MetaIO::read()
 */
Metadata* MetaIOFLACVorbis::read(QString filename)
{
    TagLib::FLAC::File *flacfile = OpenFile(filename);
    
    if (!flacfile)
        return NULL;
    
    TagLib::Ogg::XiphComment *tag = flacfile->xiphComment();
    
    if (!tag)
    {
        delete flacfile;
        return NULL;
    }
    
    Metadata *metadata = new Metadata(filename);
    
    ReadGenericMetadata(tag, metadata);
    
    bool compilation = false;

    if (tag->contains("COMPILATION_ARTIST"))
    {
        QString compilation_artist = TStringToQString(
            tag->fieldListMap()["COMPILATION_ARTIST"].toString()).trimmed();
        if (compilation_artist != metadata->Artist())
        {
            metadata->setCompilationArtist(compilation_artist);
            compilation = true;
        }
    }
    
    if (!compilation && tag->contains("MUSICBRAINZ_ALBUMARTISTID"))
    {
        QString musicbrainzcode = TStringToQString(
        tag->fieldListMap()["MUSICBRAINZ_ALBUMARTISTID"].toString()).trimmed();
        if (musicbrainzcode == MYTH_MUSICBRAINZ_ALBUMARTIST_UUID)
            compilation = true;
    }

    metadata->setCompilation(compilation);

    if (metadata->Length() <= 0)
    {
        TagLib::FileRef *fileref = new TagLib::FileRef(flacfile);
        metadata->setLength(getTrackLength(fileref));
        // FileRef takes ownership of flacfile, and is responsible for it's
        // deletion. Messy.
        delete fileref;
    }
    else
        delete flacfile;
    
    return metadata;
}
示例#6
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;
	}
}
示例#7
0
/*!
* \copydoc MetaIO::read()
*/
Metadata* MetaIOOggVorbis::read(const QString &filename)
{
    TagLib::Ogg::Vorbis::File *oggfile = OpenFile(filename);

    if (!oggfile)
        return NULL;

    TagLib::Ogg::XiphComment *tag = oggfile->tag();

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

    Metadata *metadata = new Metadata(filename);

    ReadGenericMetadata(tag, metadata);

    bool compilation = false;

    if (tag->contains("COMPILATION_ARTIST"))
    {
        QString compilation_artist = TStringToQString(
            tag->fieldListMap()["COMPILATION_ARTIST"].toString()).trimmed();
        if (compilation_artist != metadata->Artist())
        {
            metadata->setCompilationArtist(compilation_artist);
            compilation = true;
        }
    }

    if (!compilation && tag->contains("MUSICBRAINZ_ALBUMARTISTID"))
    {
        QString musicbrainzcode = TStringToQString(
        tag->fieldListMap()["MUSICBRAINZ_ALBUMARTISTID"].toString()).trimmed();
        if (musicbrainzcode == MYTH_MUSICBRAINZ_ALBUMARTIST_UUID)
            compilation = true;
    }

    metadata->setCompilation(compilation);

    if (metadata->Length() <= 0)
        metadata->setLength(getTrackLength(oggfile));
    else
        delete oggfile;

    return metadata;
}
示例#8
0
文件: taglib_ext.cpp 项目: pft/taggit
/**
 * 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;
    }
}
示例#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
QPixmap VorbisMetaDataModel::cover()
{
    TagLib::Ogg::Vorbis::File file(m_path.toLocal8Bit().constData());
    TagLib::Ogg::XiphComment *tag = file.tag();
    if(!tag)
        return QPixmap();
    TagLib::StringList list = tag->fieldListMap()["METADATA_BLOCK_PICTURE"];
    if(list.isEmpty())
        return QPixmap();
    for(uint i = 0; i < list.size(); ++i)
    {
        TagLib::String value = list[i];
        QByteArray block = QByteArray::fromBase64(TStringToQString_qt4(value).toAscii());
        if(block.size() < 32)
            continue;
        qint64 pos = 0;
        if(readPictureBlockField(block, pos) != 3) //picture type, use front cover only
            continue;
        pos += 4;
        int mimeLength = readPictureBlockField(block, pos); //mime type length
        pos += 4;
        pos += mimeLength; //skip mime type
        int descLength = readPictureBlockField(block, pos); //description length
        pos += 4;
        pos += descLength; //skip description
        pos += 4; //width
        pos += 4; //height
        pos += 4; //color depth
        pos += 4; //the number of colors used
        int length = readPictureBlockField(block, pos); //picture size
        pos += 4;
        QPixmap cover;
        cover.loadFromData(block.mid(pos, length)); //read binary picture data
        return cover;
    }
    return QPixmap();
}
示例#11
0
/*!
 * \copydoc MetaIO::write()
 */
bool MetaIOFLACVorbis::write(Metadata* mdata)
{
    if (!mdata)
        return false;

    TagLib::FLAC::File *flacfile = OpenFile(mdata->Filename());
    
    if (!flacfile)
        return false;
    
    TagLib::Ogg::XiphComment *tag = flacfile->xiphComment();
    
    if (!tag)
    {
        delete flacfile;
        return false;
    }
    
    WriteGenericMetadata(tag, mdata);

    // Compilation
    if (mdata->Compilation())
    {
        tag->addField("MUSICBRAINZ_ALBUMARTISTID",
                          MYTH_MUSICBRAINZ_ALBUMARTIST_UUID, true);
        tag->addField("COMPILATION_ARTIST",
                        QStringToTString(mdata->CompilationArtist()), true);
    }
    else
    {
        // Don't remove the musicbrainz field unless it indicated a compilation
        if (tag->contains("MUSICBRAINZ_ALBUMARTISTID") &&
            (tag->fieldListMap()["MUSICBRAINZ_ALBUMARTISTID"].toString() ==
                MYTH_MUSICBRAINZ_ALBUMARTIST_UUID))
        {
            tag->removeField("MUSICBRAINZ_ALBUMARTISTID");
        }
        tag->removeField("COMPILATION_ARTIST");
    }

    bool result = flacfile->save();

    if (flacfile)
        delete flacfile;

    return (result);
}
示例#12
0
int main(int argc, char *argv[])
{
  for(int i = 1; i < argc; i++) {

    cout << "******************** \"" << argv[i] << "\" ********************" << endl;

    TagLib::FileRef f(argv[i]);

    if(!f.isNull() && f.tag()) {

      TagLib::Tag *tag = f.tag();

      cout << "-- TAG --" << endl;
      cout << "title        - \"" << tag->title()   << "\"" << endl;
      cout << "artist       - \"" << tag->artist()  << "\"" << endl;
      cout << "album artist - \"" << tag->albumArtist()   << "\"" << endl;
      cout << "album        - \"" << tag->album()   << "\"" << endl;
      cout << "year         - \"" << tag->year()    << "\"" << endl;
      cout << "comment      - \"" << tag->comment() << "\"" << endl;
      cout << "track        - \"" << tag->track()   << "\"" << endl;
      cout << "genre        - \"" << tag->genre()   << "\"" << endl;
      cout << "grouping     - \"" << tag->grouping()   << "\"" << endl;
      TagLib::Ogg::XiphComment *comment = NULL;
      TagLib::FLAC::File *flac = dynamic_cast<TagLib::FLAC::File *>(f.file());
      if (flac) {
        cout << "flac:" << endl;
        cout << "id3v1   - \"" << flac->ID3v1Tag()   << "\"" << endl;
        cout << "id3v2   - \"" << flac->ID3v2Tag()   << "\"" << endl;
        cout << "xiph    - \"" << flac->xiphComment()   << "\"" << endl;
        comment = flac->xiphComment();
      }
      if (!comment) {
        comment = dynamic_cast<TagLib::Ogg::XiphComment *>(tag);
      }
      if (comment) {
        TagLib::Ogg::FieldListMap fields = comment->fieldListMap();
        for(TagLib::Ogg::FieldListMap::ConstIterator it = fields.begin(), end = fields.end(); it != end; it++) {
          if (!it->second.isEmpty())
            cout << "xiph:" << it->first << " \"" << it->second[0].substr(0,3) << "\"" << endl;
        }
      }
      cout << "pictures- \"" << f.file()->pictures().size()   << "\"" << endl;
      TagLib::File::PictureList l = f.file()->pictures();
      for (TagLib::File::_PictureList::ConstIterator i = l.begin(), end = l.end(); i != end; i++) {
        cout << "\t" << (*i)->typeName() << ' ' << (*i)->mimeType() << ' ' << (*i)->base64data().size() << endl;
      }
      
      cout << "pictures- \"" << tag->pictures().size()   << "\"" << endl;
    }

    if(!f.isNull() && f.audioProperties()) {

      TagLib::AudioProperties *properties = f.audioProperties();

      int seconds = properties->length() % 60;
      int minutes = (properties->length() - seconds) / 60;

      cout << "-- AUDIO --" << endl;
      cout << "bitrate     - " << properties->bitrate() << endl;
      cout << "sample rate - " << properties->sampleRate() << endl;
      cout << "channels    - " << properties->channels() << endl;
      cout << "length      - " << minutes << ":" << formatSeconds(seconds) << endl;
    }
  }
  return 0;
}