Пример #1
0
int flac_write( const char* filename, const char *predicate, const char* uri )
{
	if (strcmp(predicate, LL_LICENSE) != 0) {
		return -LL_E_MODULE_WRITE_FAIL; /* We only know License */
	}
	int ret = 1;

	FLAC__Metadata_SimpleIterator *iter = FLAC__metadata_simple_iterator_new();
	if (FLAC__metadata_simple_iterator_init(iter,filename,false,false) && FLAC__metadata_simple_iterator_is_writable(iter)) {
		FLAC__bool found_vc = false;
		do {
			if (FLAC__metadata_simple_iterator_get_block_type(iter) == FLAC__METADATA_TYPE_VORBIS_COMMENT) {
				FLAC__StreamMetadata *vc;

				found_vc = true;
				vc = FLAC__metadata_simple_iterator_get_block(iter);

				if (uri) {
					FLAC__StreamMetadata_VorbisComment_Entry entry;
					FLAC__metadata_object_vorbiscomment_entry_from_name_value_pair(&entry, "LICENSE", uri);
					FLAC__metadata_object_vorbiscomment_replace_comment(vc,entry,true,false);
				} else {
					int i = FLAC__metadata_object_vorbiscomment_find_entry_from(vc,0,"LICENSE");
					if (i != -1) {
						FLAC__metadata_object_vorbiscomment_delete_comment(vc,i);
					}
				}

				ret = FLAC__metadata_simple_iterator_set_block(iter, vc, true);
				FLAC__metadata_object_delete(vc);
				break;
			}
		} while (FLAC__metadata_simple_iterator_next(iter));

		if (!found_vc && uri) {
			FLAC__StreamMetadata *vc = FLAC__metadata_object_new(FLAC__METADATA_TYPE_VORBIS_COMMENT);

			FLAC__StreamMetadata_VorbisComment_Entry entry;
			FLAC__metadata_object_vorbiscomment_entry_from_name_value_pair(&entry, "LICENSE", uri);
			FLAC__metadata_object_vorbiscomment_append_comment(vc,entry,false);

			ret = FLAC__metadata_simple_iterator_insert_block_after(iter,vc,true);
			FLAC__metadata_object_delete(vc);
		}
	} else {
		ret = 0;
	}

	FLAC__metadata_simple_iterator_delete(iter);

	return ret;
}
Пример #2
0
bool FlacAudioEncoder::set_tag_value(FLAC__StreamMetadata* metadata, const std::string& key, const std::string& value)
{
   FLAC__StreamMetadata_VorbisComment_Entry entry;

   return FLAC__metadata_object_vorbiscomment_entry_from_name_value_pair(&entry, key.c_str(), value.c_str()) and
          FLAC__metadata_object_vorbiscomment_append_comment(metadata, entry, false);
}
Пример #3
0
	void AddCommentField(const std::string &field, const mpt::ustring &data)
	{
		if(!field.empty() && !data.empty())
		{
			FLAC__StreamMetadata_VorbisComment_Entry entry;
			FLAC__metadata_object_vorbiscomment_entry_from_name_value_pair(&entry, field.c_str(), mpt::ToCharset(mpt::CharsetUTF8, data).c_str());
			FLAC__metadata_object_vorbiscomment_append_comment(flac_metadata[0], entry, false);
		}
	}
Пример #4
0
// ========================================
// Vorbis comment utilities
// ========================================
static bool
SetVorbisComment(FLAC__StreamMetadata *block, const char *key, CFStringRef value)
{
	assert(NULL != block);
	assert(NULL != key);

	// Remove the existing comment with this name
	if(-1 == FLAC__metadata_object_vorbiscomment_remove_entry_matching(block, key)) {
		log4cxx::LoggerPtr logger = log4cxx::Logger::getLogger("org.sbooth.AudioEngine.AudioMetadata.FLAC");
		LOG4CXX_WARN(logger, "FLAC__metadata_object_vorbiscomment_remove_entry_matching() failed");
		return false;
	}
	
	// Nothing left to do if value is NULL
	if(NULL == value)
		return true;
	
	CFIndex valueCStringSize = CFStringGetMaximumSizeForEncoding(CFStringGetLength(value), kCFStringEncodingUTF8)  + 1;
	char valueCString [valueCStringSize];
	
	if(!CFStringGetCString(value, valueCString, valueCStringSize, kCFStringEncodingUTF8)) {
		log4cxx::LoggerPtr logger = log4cxx::Logger::getLogger("org.sbooth.AudioEngine.AudioMetadata.FLAC");
		LOG4CXX_WARN(logger, "CFStringGetCString() failed");
		return false;
	}
	
	FLAC__StreamMetadata_VorbisComment_Entry entry;
	
	if(!FLAC__metadata_object_vorbiscomment_entry_from_name_value_pair(&entry, key, valueCString)) {
		log4cxx::LoggerPtr logger = log4cxx::Logger::getLogger("org.sbooth.AudioEngine.AudioMetadata.FLAC");
		LOG4CXX_WARN(logger, "FLAC__metadata_object_vorbiscomment_entry_from_name_value_pair() failed");
		return false;
	}
	
	if(!FLAC__metadata_object_vorbiscomment_replace_comment(block, entry, false, false)) {
		log4cxx::LoggerPtr logger = log4cxx::Logger::getLogger("org.sbooth.AudioEngine.AudioMetadata.FLAC");
		LOG4CXX_WARN(logger, "FLAC__metadata_object_vorbiscomment_replace_comment() failed");
		return false;
	}
	
	return true;
}
Пример #5
0
/*
 * vc_block_append_single_tag:
 * @vc_block: the Vorbis comment in which to add the tag
 * @tag_name: the name of the tag
 * @value: the value of the tag
 *
 * Save field value in a single tag.
 */
static void
vc_block_append_single_tag (FLAC__StreamMetadata *vc_block,
                            const gchar *tag_name,
                            const gchar *value)
{
    FLAC__StreamMetadata_VorbisComment_Entry field;

    if (!FLAC__metadata_object_vorbiscomment_entry_from_name_value_pair (&field,
            tag_name,
            value))
    {
        g_critical ("Invalid Vorbis comment, or memory allocation failed, when creating FLAC entry from tag name '%s' and value '%s'",
                    tag_name, value);
        return;
    }

    if (!FLAC__metadata_object_vorbiscomment_append_comment (vc_block, field,
            false))
    {
        g_critical ("Invalid Vorbis comment, or memory allocation failed, when writing FLAC tag '%s' with value '%s'",
                    tag_name, value);
    }
}
/* slight modification: no 'filename' arg, and errors are passed back in 'violation' instead of printed to stderr */
static FLAC__bool set_vc_field(FLAC__StreamMetadata *block, const Argument_VcField *field, FLAC__bool *needs_write, FLAC__bool raw, const char **violation)
{
	FLAC__StreamMetadata_VorbisComment_Entry entry;
	char *converted;

	FLAC__ASSERT(0 != block);
	FLAC__ASSERT(block->type == FLAC__METADATA_TYPE_VORBIS_COMMENT);
	FLAC__ASSERT(0 != field);
	FLAC__ASSERT(0 != needs_write);

	if(field->field_value_from_file) {
		/* read the file into 'data' */
		FILE *f = 0;
		char *data = 0;
		const off_t size = grabbag__file_get_filesize(field->field_value);
		if(size < 0) {
			*violation = "can't open file for tag value";
			return false;
		}
		if(size >= 0x100000) { /* magic arbitrary limit, actual format limit is near 16MB */
			*violation = "file for tag value is too large";
			return false;
		}
		if(0 == (data = malloc(size+1)))
			die("out of memory allocating tag value");
		data[size] = '\0';
		if(0 == (f = fopen(field->field_value, "rb")) || fread(data, 1, size, f) != (size_t)size) {
			free(data);
			if(f)
				fclose(f);
			*violation = "error while reading file for tag value";
			return false;
		}
		fclose(f);
		if(strlen(data) != (size_t)size) {
			free(data);
			*violation = "file for tag value has embedded NULs";
			return false;
		}

		/* move 'data' into 'converted', converting to UTF-8 if necessary */
		if(raw) {
			converted = data;
		}
		else if(utf8_encode(data, &converted) >= 0) {
			free(data);
		}
		else {
			free(data);
			*violation = "error converting file contents to UTF-8 for tag value";
			return false;
		}

		/* create and entry and append it */
		if(!FLAC__metadata_object_vorbiscomment_entry_from_name_value_pair(&entry, field->field_name, converted)) {
			free(converted);
			*violation = "file for tag value is not valid UTF-8";
			return false;
		}
		free(converted);
		if(!FLAC__metadata_object_vorbiscomment_append_comment(block, entry, /*copy=*/false)) {
			*violation = "memory allocation failure";
			return false;
		}

		*needs_write = true;
		return true;
	}
	else {
		FLAC__bool needs_free = false;
		if(raw) {
			entry.entry = (FLAC__byte *)field->field;
		}
		else if(utf8_encode(field->field, &converted) >= 0) {
			entry.entry = (FLAC__byte *)converted;
			needs_free = true;
		}
		else {
			*violation = "error converting comment to UTF-8";
			return false;
		}
		entry.length = strlen((const char *)entry.entry);
		if(!FLAC__format_vorbiscomment_entry_is_legal(entry.entry, entry.length)) {
			if(needs_free)
				free(converted);
			/*
			 * our previous parsing has already established that the field
			 * name is OK, so it must be the field value
			 */
			*violation = "tag value for is not valid UTF-8";
			return false;
		}

		if(!FLAC__metadata_object_vorbiscomment_append_comment(block, entry, /*copy=*/true)) {
			if(needs_free)
				free(converted);
			*violation = "memory allocation failure";
			return false;
		}

		*needs_write = true;
		if(needs_free)
			free(converted);
		return true;
	}
}
Пример #7
0
Файл: main.c Проект: kode54/flac
int main(int argc, char *argv[])
{
	FLAC__bool ok = true;
	FLAC__StreamEncoder *encoder = 0;
	FLAC__StreamEncoderInitStatus init_status;
	FLAC__StreamMetadata *metadata[2];
	FLAC__StreamMetadata_VorbisComment_Entry entry;
	FILE *fin;
	unsigned sample_rate = 0;
	unsigned channels = 0;
	unsigned bps = 0;

	if(argc != 3) {
		fprintf(stderr, "usage: %s infile.wav outfile.flac\n", argv[0]);
		return 1;
	}

	if((fin = fopen(argv[1], "rb")) == NULL) {
		fprintf(stderr, "ERROR: opening %s for output\n", argv[1]);
		return 1;
	}

	/* read wav header and validate it */
	if(
		fread(buffer, 1, 44, fin) != 44 ||
		memcmp(buffer, "RIFF", 4) ||
		memcmp(buffer+8, "WAVEfmt \020\000\000\000\001\000\002\000", 16) ||
		memcmp(buffer+32, "\004\000\020\000data", 8)
	) {
		fprintf(stderr, "ERROR: invalid/unsupported WAVE file, only 16bps stereo WAVE in canonical form allowed\n");
		fclose(fin);
		return 1;
	}
	sample_rate = ((((((unsigned)buffer[27] << 8) | buffer[26]) << 8) | buffer[25]) << 8) | buffer[24];
	channels = 2;
	bps = 16;
	total_samples = (((((((unsigned)buffer[43] << 8) | buffer[42]) << 8) | buffer[41]) << 8) | buffer[40]) / 4;

	/* allocate the encoder */
	if((encoder = FLAC__stream_encoder_new()) == NULL) {
		fprintf(stderr, "ERROR: allocating encoder\n");
		fclose(fin);
		return 1;
	}

	ok &= FLAC__stream_encoder_set_verify(encoder, true);
	ok &= FLAC__stream_encoder_set_compression_level(encoder, 5);
	ok &= FLAC__stream_encoder_set_channels(encoder, channels);
	ok &= FLAC__stream_encoder_set_bits_per_sample(encoder, bps);
	ok &= FLAC__stream_encoder_set_sample_rate(encoder, sample_rate);
	ok &= FLAC__stream_encoder_set_total_samples_estimate(encoder, total_samples);

	/* now add some metadata; we'll add some tags and a padding block */
	if(ok) {
		if(
			(metadata[0] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_VORBIS_COMMENT)) == NULL ||
			(metadata[1] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)) == NULL ||
			/* there are many tag (vorbiscomment) functions but these are convenient for this particular use: */
			!FLAC__metadata_object_vorbiscomment_entry_from_name_value_pair(&entry, "ARTIST", "Some Artist") ||
			!FLAC__metadata_object_vorbiscomment_append_comment(metadata[0], entry, /*copy=*/false) || /* copy=false: let metadata object take control of entry's allocated string */
			!FLAC__metadata_object_vorbiscomment_entry_from_name_value_pair(&entry, "YEAR", "1984") ||
			!FLAC__metadata_object_vorbiscomment_append_comment(metadata[0], entry, /*copy=*/false)
		) {
			fprintf(stderr, "ERROR: out of memory or tag error\n");
			ok = false;
		}

		metadata[1]->length = 1234; /* set the padding length */

		ok = FLAC__stream_encoder_set_metadata(encoder, metadata, 2);
	}

	/* initialize encoder */
	if(ok) {
		init_status = FLAC__stream_encoder_init_file(encoder, argv[2], progress_callback, /*client_data=*/NULL);
		if(init_status != FLAC__STREAM_ENCODER_INIT_STATUS_OK) {
			fprintf(stderr, "ERROR: initializing encoder: %s\n", FLAC__StreamEncoderInitStatusString[init_status]);
			ok = false;
		}
	}

	/* read blocks of samples from WAVE file and feed to encoder */
	if(ok) {
		size_t left = (size_t)total_samples;
		while(ok && left) {
			size_t need = (left>READSIZE? (size_t)READSIZE : (size_t)left);
			if(fread(buffer, channels*(bps/8), need, fin) != need) {
				fprintf(stderr, "ERROR: reading from WAVE file\n");
				ok = false;
			}
			else {
				/* convert the packed little-endian 16-bit PCM samples from WAVE into an interleaved FLAC__int32 buffer for libFLAC */
				size_t i;
				for(i = 0; i < need*channels; i++) {
					/* inefficient but simple and works on big- or little-endian machines */
					pcm[i] = (FLAC__int32)(((FLAC__int16)(FLAC__int8)buffer[2*i+1] << 8) | (FLAC__int16)buffer[2*i]);
				}
				/* feed samples to encoder */
				ok = FLAC__stream_encoder_process_interleaved(encoder, pcm, need);
			}
			left -= need;
		}
	}

	ok &= FLAC__stream_encoder_finish(encoder);

	fprintf(stderr, "encoding: %s\n", ok? "succeeded" : "FAILED");
	fprintf(stderr, "   state: %s\n", FLAC__StreamEncoderStateString[FLAC__stream_encoder_get_state(encoder)]);

	/* now that encoding is finished, the metadata can be freed */
	FLAC__metadata_object_delete(metadata[0]);
	FLAC__metadata_object_delete(metadata[1]);

	FLAC__stream_encoder_delete(encoder);
	fclose(fin);

	return 0;
}
Пример #8
0
bool Start(void *ctx, int iInChannels, int iInRate, int iInBits,
           const char* title, const char* artist,
           const char* albumartist, const char* album,
           const char* year, const char* track, const char* genre,
           const char* comment, int iTrackLength)
{
  flac_context *context = (flac_context *)ctx;
  if (!context || !context->encoder)
    return false;

  // we accept only 2 / 44100 / 16 atm
  if (iInChannels != 2 || iInRate != 44100 || iInBits != 16)
    return false;

  FLAC__bool ok = 1;

  ok &= FLAC__stream_encoder_set_verify(context->encoder, true);
  ok &= FLAC__stream_encoder_set_channels(context->encoder, iInChannels);
  ok &= FLAC__stream_encoder_set_bits_per_sample(context->encoder, iInBits);
  ok &= FLAC__stream_encoder_set_sample_rate(context->encoder, iInRate);
  ok &= FLAC__stream_encoder_set_total_samples_estimate(context->encoder, iTrackLength / 4);
  ok &= FLAC__stream_encoder_set_compression_level(context->encoder, level);

  // now add some metadata
  FLAC__StreamMetadata_VorbisComment_Entry entry;
  if (ok)
  {
    if (
      (context->metadata[0] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_VORBIS_COMMENT)) == NULL ||
      (context->metadata[1] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)) == NULL ||
      !FLAC__metadata_object_vorbiscomment_entry_from_name_value_pair(&entry, "ARTIST", artist) ||
      !FLAC__metadata_object_vorbiscomment_append_comment(context->metadata[0], entry, false) ||
      !FLAC__metadata_object_vorbiscomment_entry_from_name_value_pair(&entry, "ALBUM", album) ||
      !FLAC__metadata_object_vorbiscomment_append_comment(context->metadata[0], entry, false) ||
      !FLAC__metadata_object_vorbiscomment_entry_from_name_value_pair(&entry, "ALBUMARTIST", albumartist) ||
      !FLAC__metadata_object_vorbiscomment_append_comment(context->metadata[0], entry, false) ||
      !FLAC__metadata_object_vorbiscomment_entry_from_name_value_pair(&entry, "TITLE", title) ||
      !FLAC__metadata_object_vorbiscomment_append_comment(context->metadata[0], entry, false) ||
      !FLAC__metadata_object_vorbiscomment_entry_from_name_value_pair(&entry, "GENRE", genre) ||
      !FLAC__metadata_object_vorbiscomment_append_comment(context->metadata[0], entry, false) ||
      !FLAC__metadata_object_vorbiscomment_entry_from_name_value_pair(&entry, "TRACKNUMBER", track) ||
      !FLAC__metadata_object_vorbiscomment_append_comment(context->metadata[0], entry, false) ||
      !FLAC__metadata_object_vorbiscomment_entry_from_name_value_pair(&entry, "DATE", year) ||
      !FLAC__metadata_object_vorbiscomment_append_comment(context->metadata[0], entry, false) ||
      !FLAC__metadata_object_vorbiscomment_entry_from_name_value_pair(&entry, "COMMENT", comment) ||
      !FLAC__metadata_object_vorbiscomment_append_comment(context->metadata[0], entry, false)
      )
    {
      ok = false;
    }
    else
    {
      context->metadata[1]->length = 4096;
      ok = FLAC__stream_encoder_set_metadata(context->encoder, context->metadata, 2);
    }
  }

  // initialize encoder in stream mode
  if (ok)
  {
    FLAC__StreamEncoderInitStatus init_status;
    init_status = FLAC__stream_encoder_init_stream(context->encoder, write_callback_flac, seek_callback_flac, tell_callback_flac, NULL, context);
    if (init_status != FLAC__STREAM_ENCODER_INIT_STATUS_OK)
    {
      ok = false;
    }
  }

  if (!ok)
  {
    return false;
  }

  return true;
}
Пример #9
0
const char*
_edje_multisense_encode_to_flac(char *snd_path, SF_INFO sfinfo)
{
   unsigned int total_samples = 0; /* can use a 32-bit number due to WAVE size limitations */
   FLAC__bool ok = 1;
   FLAC__StreamEncoder *encoder = 0;
   FLAC__StreamEncoderInitStatus init_status;
   FLAC__StreamMetadata *metadata[2];
   FLAC__StreamMetadata_VorbisComment_Entry entry;
   SNDFILE *sfile;
   sf_count_t size;
   char *tmp;

   sfile = sf_open(snd_path, SFM_READ, &sfinfo);
   if (!sfile) return NULL;
   if (!sf_format_check(&sfinfo))
     {
        sf_close(sfile);
        return NULL;
     }
   size = sf_seek(sfile, 0, SEEK_END);
   sf_seek(sfile, 0, SEEK_SET);
   tmp = malloc(strlen(snd_path) + 1 + 5);
   if (!tmp)
     {
        sf_close(sfile);
        return NULL;
     }
   strcpy(tmp, snd_path);
   snd_path = tmp;
   strcat(snd_path, ".flac");

   total_samples = size;

   /* allocate the encoder */
   if ((encoder = FLAC__stream_encoder_new()) == NULL)
     {
        ERR("ERROR: Creating FLAC encoder\n");
        free(snd_path);
        sf_close(sfile);
        return NULL;
     }

   /* Verify it's own encoded output. This will slow the encoding process. */
   ok &= FLAC__stream_encoder_set_verify(encoder, 1);

   //Levels range from 0 (fastest, least compression) to 8 (slowest, most compression).
   //A value larger than 8 will be treated as 8.
   //5 is used for good compression and moderate compression/decompression speed.
   ok &= FLAC__stream_encoder_set_compression_level(encoder, 5);
   ok &= FLAC__stream_encoder_set_channels(encoder, sfinfo.channels);
   ok &= FLAC__stream_encoder_set_bits_per_sample(encoder, 16);
   ok &= FLAC__stream_encoder_set_sample_rate(encoder, sfinfo.samplerate);
   ok &= FLAC__stream_encoder_set_total_samples_estimate(encoder, total_samples);

   /* now add some metadata; we'll add some tags and a padding block */
   if (ok)
     {
        if ((metadata[0] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_VORBIS_COMMENT)) == NULL
            || (metadata[1] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)) == NULL
            || !FLAC__metadata_object_vorbiscomment_entry_from_name_value_pair(&entry, "Encoder", "flac")
            || !FLAC__metadata_object_vorbiscomment_append_comment(metadata[0], entry, 0))
          {
             ERR("ERROR: out of memory error or tag error\n");
             ok = 0;
          }
        metadata[1]->length = 16; /* set the padding length */
        ok = FLAC__stream_encoder_set_metadata(encoder, metadata, 2);
     }

   /* initialize encoder */
   if (ok)
     {
        init_status = FLAC__stream_encoder_init_file(encoder, snd_path, NULL,
                                                     (void *)(long)(total_samples));
        if (init_status != FLAC__STREAM_ENCODER_INIT_STATUS_OK)
          {
             ERR("ERROR: unable to initialize FLAC encoder: %s\n",
                 FLAC__StreamEncoderInitStatusString[init_status]);
             ok = 0;
          }
     }
   
   /* read blocks of samples from WAVE file and feed to encoder */
   while (ok)
     {
        FLAC__int32 readbuffer[READBUF * 2];
        sf_count_t count;
        int i;
        
        count = sf_readf_int(sfile, readbuffer, READBUF);
        if (count <= 0) break;
        for (i = 0; i < (count * sfinfo.channels); i++)
          readbuffer[i] = readbuffer[i] >> 16;
        ok = FLAC__stream_encoder_process_interleaved(encoder, readbuffer,
                                                      count);
     }

   FLAC__stream_encoder_finish(encoder);
   /* now that encoding is finished, the metadata can be freed */
   FLAC__metadata_object_delete(metadata[0]);
   FLAC__metadata_object_delete(metadata[1]);

   FLAC__stream_encoder_delete(encoder);
   sf_close(sfile);
   return (snd_path);
}
Пример #10
0
bool CEncoderFlac::Start(int inChannels, int inRate, int inBits,
                         const std::string& title, const std::string& artist,
                         const std::string& albumartist, const std::string& album,
                         const std::string& year, const std::string& track, const std::string& genre,
                         const std::string& comment, int trackLength)
{
  if (!m_encoder)
    return false;

  // we accept only 2 / 44100 / 16 atm
  if (inChannels != 2 || inRate != 44100 || inBits != 16)
  {
    kodi::Log(ADDON_LOG_ERROR, "Invalid input format to encode");
    return false;
  }

  FLAC__bool ok = 1;

  ok &= FLAC__stream_encoder_set_verify(m_encoder, true);
  ok &= FLAC__stream_encoder_set_channels(m_encoder, inChannels);
  ok &= FLAC__stream_encoder_set_bits_per_sample(m_encoder, inBits);
  ok &= FLAC__stream_encoder_set_sample_rate(m_encoder, inRate);
  ok &= FLAC__stream_encoder_set_total_samples_estimate(m_encoder, trackLength / 4);
  ok &= FLAC__stream_encoder_set_compression_level(m_encoder, kodi::GetSettingInt("level"));

  // now add some metadata
  FLAC__StreamMetadata_VorbisComment_Entry entry;
  if (ok)
  {
    if (
      (m_metadata[0] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_VORBIS_COMMENT)) == nullptr ||
      (m_metadata[1] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)) == nullptr ||
      !FLAC__metadata_object_vorbiscomment_entry_from_name_value_pair(&entry, "ARTIST", artist.c_str()) ||
      !FLAC__metadata_object_vorbiscomment_append_comment(m_metadata[0], entry, false) ||
      !FLAC__metadata_object_vorbiscomment_entry_from_name_value_pair(&entry, "ALBUM", album.c_str()) ||
      !FLAC__metadata_object_vorbiscomment_append_comment(m_metadata[0], entry, false) ||
      !FLAC__metadata_object_vorbiscomment_entry_from_name_value_pair(&entry, "ALBUMARTIST", albumartist.c_str()) ||
      !FLAC__metadata_object_vorbiscomment_append_comment(m_metadata[0], entry, false) ||
      !FLAC__metadata_object_vorbiscomment_entry_from_name_value_pair(&entry, "TITLE", title.c_str()) ||
      !FLAC__metadata_object_vorbiscomment_append_comment(m_metadata[0], entry, false) ||
      !FLAC__metadata_object_vorbiscomment_entry_from_name_value_pair(&entry, "GENRE", genre.c_str()) ||
      !FLAC__metadata_object_vorbiscomment_append_comment(m_metadata[0], entry, false) ||
      !FLAC__metadata_object_vorbiscomment_entry_from_name_value_pair(&entry, "TRACKNUMBER", track.c_str()) ||
      !FLAC__metadata_object_vorbiscomment_append_comment(m_metadata[0], entry, false) ||
      !FLAC__metadata_object_vorbiscomment_entry_from_name_value_pair(&entry, "DATE", year.c_str()) ||
      !FLAC__metadata_object_vorbiscomment_append_comment(m_metadata[0], entry, false) ||
      !FLAC__metadata_object_vorbiscomment_entry_from_name_value_pair(&entry, "COMMENT", comment.c_str()) ||
      !FLAC__metadata_object_vorbiscomment_append_comment(m_metadata[0], entry, false)
      )
    {
      ok = false;
    }
    else
    {
      m_metadata[1]->length = 4096;
      ok = FLAC__stream_encoder_set_metadata(m_encoder, m_metadata, 2);
    }
  }

  // initialize encoder in stream mode
  if (ok)
  {
    FLAC__StreamEncoderInitStatus init_status;
    init_status = FLAC__stream_encoder_init_stream(m_encoder, write_callback_flac, seek_callback_flac, tell_callback_flac, nullptr, this);
    if (init_status != FLAC__STREAM_ENCODER_INIT_STATUS_OK)
    {
      ok = false;
    }
  }

  if (!ok)
  {
    kodi::Log(ADDON_LOG_ERROR, "Failed to create flac stream encoder");
    return false;
  }

  return true;
}