Search code examples
c++oggvorbis

Write vorbis comment metadata (tags) to the existing FLAC file using libFLAC++


How to write vorbis comments metadata, i.e. tags (for example "TITLE"), to the existing FLAC file using libFLAC++ (http://flac.sourceforge.net)?

For example:

const char* fileName = "/path/to/file.flac";

// read tags from the file
FLAC::Metadata::VorbisComment vorbisComment;
FLAC::Metadata::get_tags(fileName, vorbisComment);

// make some changes
vorbisComment.append_comment("TITLE", "This is title");

// write changes back to the file ...
// :-( there is no API for that, i.e. something like this:
// FLAC::Metadata::write_tags(fileName, vorbisComment);

Solution

  • I've analysed metaflac source code (as suggested) and here is a solution to the problem:

    #include <FLAC++/metadata.h>
    
    const char* fileName = "/path/to/file.flac";
    
    // read a file using FLAC::Metadata::Chain class
    FLAC::Metadata::Chain chain;
    if (!chain.read(fileName)) {
        // error handling
        throw ...;
    }
    
    // now, find vorbis comment block and make changes in it
    {
        FLAC::Metadata::Iterator iterator;
        iterator.init(chain);
    
        // find vorbis comment block
        FLAC::Metadata::VorbisComment* vcBlock = 0;
        do {
            FLAC::Metadata::Prototype* block = iterator.get_block();
            if (block->get_type() == FLAC__METADATA_TYPE_VORBIS_COMMENT) {
                vcBlock = (FLAC::Metadata::VorbisComment*) block;
                break;
            }
        } while (iterator.next());
    
        // if not found, create a new one
        if (vcBlock == 0) {
            // create a new block
            vcBlock = new FLAC::Metadata::VorbisComment();
    
            // move iterator to the end
            while (iterator.next()) {
            }
    
            // insert a new block at the end
            if (!iterator.insert_block_after(vcBlock)) {
                delete vcBlock;
                // error handling
                throw ...;
            }
        }
    
        // now, you can make any number of changes to the vorbis comment block,
        // for example you can append TITLE comment:
        vcBlock->append_comment(
            FLAC::Metadata::VorbisComment::Entry("TITLE", "This is title"));
    }
    
    // write changes back to the file
    if (!chain.write()) {
        // error handling
        throw ...;
    }