Ejemplo n.º 1
0
CEncoderFlac::~CEncoderFlac()
{
  // free the metadata
  if (m_metadata[0])
    FLAC__metadata_object_delete(m_metadata[0]);
  if (m_metadata[1])
    FLAC__metadata_object_delete(m_metadata[1]);

  // free the encoder
  if (m_encoder)
    FLAC__stream_encoder_delete(m_encoder);
}
Ejemplo n.º 2
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;
}
Ejemplo n.º 3
0
FLAC__bool do_shorthand_operation__add_padding(const char *filename, FLAC__Metadata_Chain *chain, unsigned length, FLAC__bool *needs_write)
{
	FLAC__StreamMetadata *padding = 0;
	FLAC__Metadata_Iterator *iterator = FLAC__metadata_iterator_new();

	if(0 == iterator)
		die("out of memory allocating iterator");

	FLAC__metadata_iterator_init(iterator, chain);

	while(FLAC__metadata_iterator_next(iterator))
		;

	padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING);
	if(0 == padding)
		die("out of memory allocating PADDING block");

	padding->length = length;

	if(!FLAC__metadata_iterator_insert_block_after(iterator, padding)) {
		print_error_with_chain_status(chain, "%s: ERROR: adding new PADDING block to metadata", filename);
		FLAC__metadata_object_delete(padding);
		FLAC__metadata_iterator_delete(iterator);
		return false;
	}

	FLAC__metadata_iterator_delete(iterator);
	*needs_write = true;
	return true;
}
Ejemplo n.º 4
0
	void FinishStream()
	{
		if(inited)
		{
			if(!started)
			{
				StartStream();
			}
			ASSERT(inited && started);

			FLAC__stream_encoder_finish(encoder);
			FLAC__stream_encoder_delete(encoder);
			encoder = nullptr;

			if(flac_metadata[0])
			{
				FLAC__metadata_object_delete(flac_metadata[0]);
				flac_metadata[0] = nullptr;
			}

			started = false;
			inited = false;
		}
		ASSERT(!inited && !started);
	}
Ejemplo n.º 5
0
void FlacAudioEncoder::tear_down()
{
   if (not FLAC__stream_encoder_finish(_encoder))
   {
      THROW_EXCEPTION(AudioEncoderException, "ERROR: could not finish encoding");
   }

   FLAC__metadata_object_delete(_metadata[0]);
   FLAC__metadata_object_delete(_metadata[1]);

   if (_encoder)
   {
      FLAC__stream_encoder_delete(_encoder);
      _encoder = nullptr;
   }
}
Ejemplo n.º 6
0
static void
DeleteFlacMetaArray(FlacEncodeInfo *fei)
{
    for (int i=0; i<FMT_NUM; ++i) {
        FLAC__metadata_object_delete(fei->flacMetaArray[i]);
        fei->flacMetaArray[i] = NULL;
    }
}
Ejemplo n.º 7
0
void Free(void *ctx)
{
  flac_context *context = (flac_context*)ctx;
  if (context)
  {
    // free the metadata
    if (context->metadata[0])
      FLAC__metadata_object_delete(context->metadata[0]);
    if (context->metadata[1])
      FLAC__metadata_object_delete(context->metadata[1]);

    // free the encoder
    if (context->encoder)
      FLAC__stream_encoder_delete(context->encoder);

    delete context;
  }
}
Ejemplo n.º 8
0
void flac_metadata(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
{
    CFlacDec * flacdec = (CFlacDec *)client_data;
    (void)decoder;

    switch (metadata->type)
    {
    case FLAC__METADATA_TYPE_STREAMINFO:
    {
        printf("STREAMINFO block received\n");
        flacdec->mTotalSamples = metadata->data.stream_info.total_samples;
        flacdec->mBps = metadata->data.stream_info.bits_per_sample;
        flacdec->mChannels = metadata->data.stream_info.channels;
        flacdec->mSampleRate = metadata->data.stream_info.sample_rate;

        {
            /* with VC++ you have to spoon feed it the casting from uint64->int64->double */
            FLAC__uint64 l = (FLAC__uint64)((double)(FLAC__int64)flacdec->mTotalSamples / (double)flacdec->mSampleRate * 1000.0 + 0.5);
            if (l > INT_MAX)
                l = INT_MAX;
            flacdec->mLengthInMsec = (int)l;
        }
        break;
    }
    case FLAC__METADATA_TYPE_PADDING:
        printf("PADDING block received\n");
        break;
    case FLAC__METADATA_TYPE_APPLICATION:
        printf("APPLICATION block received\n");
        break;
    case FLAC__METADATA_TYPE_SEEKTABLE:
        printf("SEEKTABLE block received\n");
        break;
    case FLAC__METADATA_TYPE_VORBIS_COMMENT:
    {
        printf("VORBISCOMMENT block (a.k.a. FLAC tags) received\n");
        // if there is an old metadata -> clear it
        if (flacdec->mMetadata != NULL)
            FLAC__metadata_object_delete(flacdec->mMetadata);
        flacdec->mMetadata = FLAC__metadata_object_clone(metadata);
        break;
    }
    case FLAC__METADATA_TYPE_CUESHEET:
        printf("CUESHEET block received\n");
        break;
    case FLAC__METADATA_TYPE_PICTURE:
        printf("PICTURE block received\n");
        break;
    case FLAC__METADATA_TYPE_UNDEFINED:
    default:
        printf("Undefined block received\n");
        break;
    }
}
Ejemplo n.º 9
0
Archivo: main.c Proyecto: ACUVE/flac
static FLAC__bool test_one_picture(const char *prefix, const PictureFile *pf, const PictureResolution * res, FLAC__bool fn_only)
{
	FLAC__StreamMetadata *obj;
	const char *error;
	char s[4096];
	if(fn_only)
		flac_snprintf(s, sizeof(s), "pictures/%s", pf->path);
	else if (res == NULL)
		flac_snprintf(s, sizeof(s), "%u|%s|%s||pictures/%s", (unsigned)pf->type, pf->mime_type, pf->description, pf->path);
	else
		flac_snprintf(s, sizeof(s), "%u|%s|%s|%dx%dx%d/%d|pictures/%s", (unsigned)pf->type, pf->mime_type, pf->description, res->width, res->height, res->depth, res->colors, pf->path);

	printf("testing grabbag__picture_parse_specification(\"%s\")... ", s);

	flac_snprintf(s, sizeof(s), "%s/%s", prefix, pf->path);
	if((obj = grabbag__picture_from_specification(fn_only? FLAC__STREAM_METADATA_PICTURE_TYPE_FRONT_COVER : pf->type, pf->mime_type, pf->description, res, s, &error)) == 0)
		return failed_(error);
	if(debug_) {
		printf("\ntype=%u (%s)\nmime_type=%s\ndescription=%s\nwidth=%u\nheight=%u\ndepth=%u\ncolors=%u\ndata_length=%u\n",
			obj->data.picture.type,
			obj->data.picture.type < FLAC__STREAM_METADATA_PICTURE_TYPE_UNDEFINED?
				FLAC__StreamMetadata_Picture_TypeString[obj->data.picture.type] : "UNDEFINED",
			obj->data.picture.mime_type,
			obj->data.picture.description,
			obj->data.picture.width,
			obj->data.picture.height,
			obj->data.picture.depth,
			obj->data.picture.colors,
			obj->data.picture.data_length
		);
	}
	if(obj->data.picture.type != (fn_only? FLAC__STREAM_METADATA_PICTURE_TYPE_FRONT_COVER : pf->type))
		return failed_("picture type mismatch");
	if(strcmp(obj->data.picture.mime_type, pf->mime_type))
		return failed_("picture MIME type mismatch");
	if(strcmp((const char *)obj->data.picture.description, (const char *)pf->description))
		return failed_("picture description mismatch");
	if(obj->data.picture.width != pf->width)
		return failed_("picture width mismatch");
	if(obj->data.picture.height != pf->height)
		return failed_("picture height mismatch");
	if(obj->data.picture.depth != pf->depth)
		return failed_("picture depth mismatch");
	if(obj->data.picture.colors != pf->colors)
		return failed_("picture colors mismatch");
	printf("OK\n");
	FLAC__metadata_object_delete(obj);
	return true;
}
Ejemplo n.º 10
0
static int stop_write(sox_format_t * const ft)
{
  priv_t * p = (priv_t *)ft->priv;
  FLAC__StreamEncoderState state = FLAC__stream_encoder_get_state(p->encoder);
  unsigned i;

  FLAC__stream_encoder_finish(p->encoder);
  FLAC__stream_encoder_delete(p->encoder);
  for (i = 0; i < p->num_metadata; ++i)
    FLAC__metadata_object_delete(p->metadata[i]);
  free(p->decoded_samples);
  if (state != FLAC__STREAM_ENCODER_OK) {
    lsx_fail_errno(ft, SOX_EINVAL, "FLAC ERROR: failed to encode to end of stream");
    return SOX_EOF;
  }
  return SOX_SUCCESS;
}
Ejemplo n.º 11
0
char* flac_read( const char* filename, const ll_uri_t predicate )
{
	if (strcmp(predicate, LL_LICENSE) != 0) {
		return -LL_E_MODULE_WRITE_FAIL; /* We only know License */
	}
	char *license = NULL;

	FLAC__StreamMetadata *vc;
	if ( FLAC__metadata_get_tags(filename,&vc) ) {
		int idx = FLAC__metadata_object_vorbiscomment_find_entry_from(vc, 0, "LICENSE");
		if (idx != -1) {
			license = strdup((char*)&vc->data.vorbis_comment.comments[idx].entry[8]);
		}
		FLAC__metadata_object_delete(vc);
	}

	return license;
}
Ejemplo n.º 12
0
static void
xmms_flac_destroy (xmms_xform_t *xform)
{
	xmms_flac_data_t *data;

	g_return_if_fail (xform);

	data = xmms_xform_private_data_get (xform);
	g_return_if_fail (data);

	if (data->vorbiscomment) {
		FLAC__metadata_object_delete (data->vorbiscomment);
	}

	g_string_free (data->buffer, TRUE);

	FLAC__stream_decoder_finish (data->flacdecoder);
	FLAC__stream_decoder_delete (data->flacdecoder);

	g_free (data);
}
Ejemplo n.º 13
0
FLAC__StreamMetadata *grabbag__cuesheet_parse(FILE *file, const char **error_message, unsigned *last_line_read, FLAC__bool is_cdda, FLAC__uint64 lead_out_offset)
{
	FLAC__StreamMetadata *cuesheet;

	FLAC__ASSERT(0 != file);
	FLAC__ASSERT(0 != error_message);
	FLAC__ASSERT(0 != last_line_read);

	*last_line_read = 0;
	cuesheet = FLAC__metadata_object_new(FLAC__METADATA_TYPE_CUESHEET);

	if(0 == cuesheet) {
		*error_message = "memory allocation error";
		return 0;
	}

	if(!local__cuesheet_parse_(file, error_message, last_line_read, cuesheet, is_cdda, lead_out_offset)) {
		FLAC__metadata_object_delete(cuesheet);
		return 0;
	}

	return cuesheet;
}
Ejemplo n.º 14
0
void FLAC_plugin__vorbiscomment_get(const char *filename, FLAC_Plugin__CanonicalTag *tag)
{
	FLAC__Metadata_SimpleIterator *iterator = FLAC__metadata_simple_iterator_new();
	if(0 != iterator) {
		if(FLAC__metadata_simple_iterator_init(iterator, filename, /*read_only=*/true, /*preserve_file_stats=*/true)) {
			FLAC__bool got_vorbis_comments = false;
			do {
				if(FLAC__metadata_simple_iterator_get_block_type(iterator) == FLAC__METADATA_TYPE_VORBIS_COMMENT) {
					FLAC__StreamMetadata *block = FLAC__metadata_simple_iterator_get_block(iterator);
					if(0 != block) {
						unsigned i;
						const FLAC__StreamMetadata_VorbisComment *vc = &block->data.vorbis_comment;
						for(i = 0; i < vc->num_comments; i++) {
							if(local__vcentry_matches("artist", &vc->comments[i]))
								local__vcentry_parse_value(&vc->comments[i], &tag->composer);
							else if(local__vcentry_matches("performer", &vc->comments[i]))
								local__vcentry_parse_value(&vc->comments[i], &tag->performer);
							else if(local__vcentry_matches("album", &vc->comments[i]))
								local__vcentry_parse_value(&vc->comments[i], &tag->album);
							else if(local__vcentry_matches("title", &vc->comments[i]))
								local__vcentry_parse_value(&vc->comments[i], &tag->title);
							else if(local__vcentry_matches("tracknumber", &vc->comments[i]))
								local__vcentry_parse_value(&vc->comments[i], &tag->track_number);
							else if(local__vcentry_matches("genre", &vc->comments[i]))
								local__vcentry_parse_value(&vc->comments[i], &tag->genre);
							else if(local__vcentry_matches("description", &vc->comments[i]))
								local__vcentry_parse_value(&vc->comments[i], &tag->comment);
						}
						FLAC__metadata_object_delete(block);
						got_vorbis_comments = true;
					}
				}
			} while (!got_vorbis_comments && FLAC__metadata_simple_iterator_next(iterator));
		}
		FLAC__metadata_simple_iterator_delete(iterator);
	}
}
Ejemplo n.º 15
0
static bool DecodeFLAC(FILE *f, FILE *of)
{
	fseek(f, 0, SEEK_SET);
	FLAC__StreamDecoder *decoder = FLAC__stream_decoder_new();
	if(decoder == nullptr)
	{
		return false;
	}

	FLAC__stream_decoder_set_metadata_respond_all(decoder);

	FLACClientData client;
	client.of = of;
	client.started = false;
	client.encoder = FLAC__stream_encoder_new();

	FLAC__StreamDecoderInitStatus initStatus = FLAC__stream_decoder_init_FILE(decoder, f, write_cb, metadata_cb, error_cb, &client);

	if(initStatus != FLAC__STREAM_DECODER_INIT_STATUS_OK || client.encoder == nullptr)
	{
		FLAC__stream_decoder_delete(decoder);
		return false;
	}

	FLAC__stream_decoder_process_until_end_of_stream(decoder);
	FLAC__stream_decoder_finish(decoder);
	FLAC__stream_decoder_delete(decoder);
	FLAC__stream_encoder_finish(client.encoder);
	FLAC__stream_encoder_delete(client.encoder);

	for(auto m = client.metadata.begin(); m != client.metadata.end(); m++)
	{
		FLAC__metadata_object_delete(*m);
	}

	return client.started;
}
Ejemplo n.º 16
0
FLAC__bool FLAC_plugin__replaygain_get_from_file(const char *filename,
                                                 double *reference, FLAC__bool *reference_set,
                                                 double *track_gain, FLAC__bool *track_gain_set,
                                                 double *album_gain, FLAC__bool *album_gain_set,
                                                 double *track_peak, FLAC__bool *track_peak_set,
                                                 double *album_peak, FLAC__bool *album_peak_set)
{
	FLAC__Metadata_SimpleIterator *iterator = FLAC__metadata_simple_iterator_new();
	FLAC__bool ret = false;

	*track_gain_set = *album_gain_set = *track_peak_set = *album_peak_set = false;

	if(0 != iterator) {
		if(FLAC__metadata_simple_iterator_init(iterator, filename, /*read_only=*/true, /*preserve_file_stats=*/true)) {
			FLAC__bool got_vorbis_comments = false;
			ret = true;
			do {
				if(FLAC__metadata_simple_iterator_get_block_type(iterator) == FLAC__METADATA_TYPE_VORBIS_COMMENT) {
					FLAC__StreamMetadata *block = FLAC__metadata_simple_iterator_get_block(iterator);
					if(0 != block) {
						if(grabbag__replaygain_load_from_vorbiscomment(block, /*album_mode=*/false, /*strict=*/true, reference, track_gain, track_peak)) {
							*reference_set = *track_gain_set = *track_peak_set = true;
						}
						if(grabbag__replaygain_load_from_vorbiscomment(block, /*album_mode=*/true, /*strict=*/true, reference, album_gain, album_peak)) {
							*reference_set = *album_gain_set = *album_peak_set = true;
						}
						FLAC__metadata_object_delete(block);
						got_vorbis_comments = true;
					}
				}
			} while (!got_vorbis_comments && FLAC__metadata_simple_iterator_next(iterator));
		}
		FLAC__metadata_simple_iterator_delete(iterator);
	}
	return ret;
}
FLAC__bool do_shorthand_operation__picture(const char *filename, FLAC__Metadata_Chain *chain, const Operation *operation, FLAC__bool *needs_write)
{
	FLAC__bool ok = true, has_type1 = false, has_type2 = false;
	FLAC__StreamMetadata *picture = 0;
	FLAC__Metadata_Iterator *iterator = FLAC__metadata_iterator_new();

	if(0 == iterator)
		die("out of memory allocating iterator");

	FLAC__metadata_iterator_init(iterator, chain);

	switch(operation->type) {
		case OP__IMPORT_PICTURE_FROM:
			ok = import_pic_from(filename, &picture, operation->argument.specification.value, needs_write);
			if(ok) {
				/* append PICTURE block */
				while(FLAC__metadata_iterator_next(iterator))
					;
				if(!FLAC__metadata_iterator_insert_block_after(iterator, picture)) {
					print_error_with_chain_status(chain, "%s: ERROR: adding new PICTURE block to metadata", filename);
					FLAC__metadata_object_delete(picture);
					ok = false;
				}
			}
			if(ok) {
				/* check global PICTURE constraints (max 1 block each of type=1 and type=2) */
				while(FLAC__metadata_iterator_prev(iterator))
					;
				do {
					FLAC__StreamMetadata *block = FLAC__metadata_iterator_get_block(iterator);
					if(block->type == FLAC__METADATA_TYPE_PICTURE) {
						if(block->data.picture.type == FLAC__STREAM_METADATA_PICTURE_TYPE_FILE_ICON_STANDARD) {
							if(has_type1) {
								print_error_with_chain_status(chain, "%s: ERROR: FLAC stream can only have one 32x32 standard icon (type=1) PICTURE block", filename);
								ok = false;
							}
							has_type1 = true;
						}
						else if(block->data.picture.type == FLAC__STREAM_METADATA_PICTURE_TYPE_FILE_ICON) {
							if(has_type2) {
								print_error_with_chain_status(chain, "%s: ERROR: FLAC stream can only have one icon (type=2) PICTURE block", filename);
								ok = false;
							}
							has_type2 = true;
						}
					}
				} while(FLAC__metadata_iterator_next(iterator));
			}
			break;
		case OP__EXPORT_PICTURE_TO:
			{
				const Argument_BlockNumber *a = operation->argument.export_picture_to.block_number_link;
				int block_number = (a && a->num_entries > 0)? (int)a->entries[0] : -1;
				unsigned i = 0;
				do {
					FLAC__StreamMetadata *block = FLAC__metadata_iterator_get_block(iterator);
					if(block->type == FLAC__METADATA_TYPE_PICTURE && (block_number < 0 || i == (unsigned)block_number))
						picture = block;
					i++;
				} while(FLAC__metadata_iterator_next(iterator) && 0 == picture);
				if(0 == picture) {
					if(block_number < 0)
						fprintf(stderr, "%s: ERROR: FLAC file has no PICTURE block\n", filename);
					else
						fprintf(stderr, "%s: ERROR: FLAC file has no PICTURE block at block #%d\n", filename, block_number);
					ok = false;
				}
				else
					ok = export_pic_to(filename, picture, operation->argument.filename.value);
			}
			break;
		default:
			ok = false;
			FLAC__ASSERT(0);
			break;
	};

	FLAC__metadata_iterator_delete(iterator);
	return ok;
}
Ejemplo n.º 18
0
Archivo: main.c Proyecto: Erikhht/TCPMP
static int do_cuesheet(const char *infilename, FLAC__bool is_cdda, FLAC__uint64 lead_out_offset)
{
	FILE *fin, *fout;
	const char *error_message;
	char tmpfilename[4096];
	unsigned last_line_read;
	FLAC__StreamMetadata *cuesheet;

	FLAC__ASSERT(strlen(infilename) + 2 < sizeof(tmpfilename));

	/*
	 * pass 1
	 */
	if(0 == strcmp(infilename, "-")) {
		fin = stdin;
	}
	else if(0 == (fin = fopen(infilename, "r"))) {
		fprintf(stderr, "can't open file %s for reading\n", infilename);
		return 255;
	}
	if(0 != (cuesheet = grabbag__cuesheet_parse(fin, &error_message, &last_line_read, is_cdda, lead_out_offset))) {
		if(fin != stdin)
			fclose(fin);
	}
	else {
		printf("pass1: parse error, line %u: \"%s\"\n", last_line_read, error_message);
		if(fin != stdin)
			fclose(fin);
		return 1;
	}
	if(!FLAC__metadata_object_cuesheet_is_legal(cuesheet, is_cdda, &error_message)) {
		printf("pass1: illegal cuesheet: \"%s\"\n", error_message);
		FLAC__metadata_object_delete(cuesheet);
		return 1;
	}
	sprintf(tmpfilename, "%s.1", infilename);
	if(0 == (fout = fopen(tmpfilename, "w"))) {
		fprintf(stderr, "can't open file %s for writing\n", tmpfilename);
		FLAC__metadata_object_delete(cuesheet);
		return 255;
	}
	grabbag__cuesheet_emit(fout, cuesheet, "\"dummy.wav\" WAVE");
	FLAC__metadata_object_delete(cuesheet);
	fclose(fout);

	/*
	 * pass 2
	 */
	if(0 == (fin = fopen(tmpfilename, "r"))) {
		fprintf(stderr, "can't open file %s for reading\n", tmpfilename);
		return 255;
	}
	if(0 != (cuesheet = grabbag__cuesheet_parse(fin, &error_message, &last_line_read, is_cdda, lead_out_offset))) {
		if(fin != stdin)
			fclose(fin);
	}
	else {
		printf("pass2: parse error, line %u: \"%s\"\n", last_line_read, error_message);
		if(fin != stdin)
			fclose(fin);
		return 1;
	}
	if(!FLAC__metadata_object_cuesheet_is_legal(cuesheet, is_cdda, &error_message)) {
		printf("pass2: illegal cuesheet: \"%s\"\n", error_message);
		FLAC__metadata_object_delete(cuesheet);
		return 1;
	}
	sprintf(tmpfilename, "%s.2", infilename);
	if(0 == (fout = fopen(tmpfilename, "w"))) {
		fprintf(stderr, "can't open file %s for writing\n", tmpfilename);
		FLAC__metadata_object_delete(cuesheet);
		return 255;
	}
	grabbag__cuesheet_emit(fout, cuesheet, "\"dummy.wav\" WAVE");
	FLAC__metadata_object_delete(cuesheet);
	fclose(fout);

	return 0;
}
FLAC__bool do_shorthand_operation__cuesheet(const char *filename, FLAC__Metadata_Chain *chain, const Operation *operation, FLAC__bool *needs_write)
{
	FLAC__bool ok = true;
	FLAC__StreamMetadata *cuesheet = 0;
	FLAC__Metadata_Iterator *iterator = FLAC__metadata_iterator_new();
	FLAC__uint64 lead_out_offset = 0;
	FLAC__bool is_cdda = false;
	unsigned sample_rate = 0;

	if(0 == iterator)
		die("out of memory allocating iterator");

	FLAC__metadata_iterator_init(iterator, chain);

	do {
		FLAC__StreamMetadata *block = FLAC__metadata_iterator_get_block(iterator);
		if(block->type == FLAC__METADATA_TYPE_STREAMINFO) {
			lead_out_offset = block->data.stream_info.total_samples;
			if(lead_out_offset == 0) {
				flac_fprintf(stderr, "%s: ERROR: FLAC file must have total_samples set in STREAMINFO in order to import/export cuesheet\n", filename);
				FLAC__metadata_iterator_delete(iterator);
				return false;
			}
			sample_rate = block->data.stream_info.sample_rate;
			is_cdda = (block->data.stream_info.channels == 1 || block->data.stream_info.channels == 2) && (block->data.stream_info.bits_per_sample == 16) && (sample_rate == 44100);
		}
		else if(block->type == FLAC__METADATA_TYPE_CUESHEET)
			cuesheet = block;
	} while(FLAC__metadata_iterator_next(iterator));

	if(lead_out_offset == 0) {
		flac_fprintf(stderr, "%s: ERROR: FLAC stream has no STREAMINFO block\n", filename);
		FLAC__metadata_iterator_delete(iterator);
		return false;
	}

	switch(operation->type) {
		case OP__IMPORT_CUESHEET_FROM:
			if(0 != cuesheet) {
				flac_fprintf(stderr, "%s: ERROR: FLAC file already has CUESHEET block\n", filename);
				ok = false;
			}
			else {
				ok = import_cs_from(filename, &cuesheet, operation->argument.import_cuesheet_from.filename, needs_write, lead_out_offset, sample_rate, is_cdda, operation->argument.import_cuesheet_from.add_seekpoint_link);
				if(ok) {
					/* append CUESHEET block */
					while(FLAC__metadata_iterator_next(iterator))
						;
					if(!FLAC__metadata_iterator_insert_block_after(iterator, cuesheet)) {
						print_error_with_chain_status(chain, "%s: ERROR: adding new CUESHEET block to metadata", filename);
						FLAC__metadata_object_delete(cuesheet);
						ok = false;
					}
				}
			}
			break;
		case OP__EXPORT_CUESHEET_TO:
			if(0 == cuesheet) {
				flac_fprintf(stderr, "%s: ERROR: FLAC file has no CUESHEET block\n", filename);
				ok = false;
			}
			else
				ok = export_cs_to(filename, cuesheet, operation->argument.filename.value);
			break;
		default:
			ok = false;
			FLAC__ASSERT(0);
			break;
	};

	FLAC__metadata_iterator_delete(iterator);
	return ok;
}
Ejemplo n.º 20
0
Archivo: main.c Proyecto: 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;
}
Ejemplo n.º 21
0
/* this is the codec entry point */
enum codec_status codec_start(struct codec_api* api)
{
    struct codec_api* ci = api;
    FLAC__SeekableStreamDecoder* flacDecoder;
    FLAC__uint64 offset;

    TEST_CODEC_API(ci);

#ifndef SIMULATOR
    ci->memcpy(iramstart, iramcopy, iramend-iramstart);
#endif

    ci->configure(CODEC_SET_FILEBUF_LIMIT, (int *)(1024*1024*10));
    ci->configure(CODEC_SET_FILEBUF_WATERMARK, (int *)(1024*512));
    ci->configure(CODEC_SET_FILEBUF_CHUNKSIZE, (int *)(1024*1024));

    ci->configure(CODEC_DSP_ENABLE, (bool *)true);
    ci->configure(DSP_DITHER, (bool *)false);
    ci->configure(DSP_SET_STEREO_MODE, (int *)STEREO_INTERLEAVED);
    ci->configure(DSP_SET_SAMPLE_DEPTH, (int *)(16));
  
next_track:
    metadata_length = 0;
    seek_table = NULL;
    stream_info = NULL;

    if (codec_init(api)) {
        return CODEC_ERROR;
    }

    while (!ci->taginfo_ready)
        ci->yield();
    
    ci->configure(DSP_SET_FREQUENCY, (long *)(ci->id3->frequency));
    codec_set_replaygain(ci->id3);
  
    /* Create a decoder instance */
    flacDecoder = FLAC__seekable_stream_decoder_new();

    /* Set up the decoder and the callback functions - this must be done before init */

    /* The following are required for stream_decoder and higher */
    FLAC__seekable_stream_decoder_set_client_data(flacDecoder,ci);
    FLAC__seekable_stream_decoder_set_write_callback(flacDecoder, flac_write_handler);
    FLAC__seekable_stream_decoder_set_read_callback(flacDecoder, flac_read_handler);
    FLAC__seekable_stream_decoder_set_metadata_callback(flacDecoder, flac_metadata_handler);
    FLAC__seekable_stream_decoder_set_error_callback(flacDecoder, flac_error_handler);
    FLAC__seekable_stream_decoder_set_metadata_respond_all(flacDecoder);

    /* The following are only for the seekable_stream_decoder */
    FLAC__seekable_stream_decoder_set_seek_callback(flacDecoder, flac_seek_handler);
    FLAC__seekable_stream_decoder_set_tell_callback(flacDecoder, flac_tell_handler);
    FLAC__seekable_stream_decoder_set_length_callback(flacDecoder, flac_length_handler);
    FLAC__seekable_stream_decoder_set_eof_callback(flacDecoder, flac_eof_handler);


    /* QUESTION: What do we do when the init fails? */
    if (FLAC__seekable_stream_decoder_init(flacDecoder)) {
        return CODEC_ERROR;
    }

    /* The first thing to do is to parse the metadata */
    FLAC__seekable_stream_decoder_process_until_end_of_metadata(flacDecoder);

    if (ci->id3->offset && stream_info) {
        FLAC__uint64 sample;

        sample = find_sample_number(ci, ci->id3->offset - metadata_length);
        ci->advance_buffer(ci->id3->offset);
        FLAC__seekable_stream_decoder_seek_absolute(flacDecoder, sample);
        FLAC__seekable_stream_decoder_get_decode_position(flacDecoder, &offset);
        ci->set_offset(offset);
        samplesdone = (uint32_t)sample;
        ci->set_elapsed(sample/(ci->id3->frequency/1000));
    } else {
        samplesdone = 0;
        ci->set_elapsed(0);
    }

    /* The main decoder loop */
    while (FLAC__seekable_stream_decoder_get_state(flacDecoder) != FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM) {
        ci->yield();
        if (ci->stop_codec || ci->reload_codec) {
            break;
        }

        if (ci->seek_time) {
            int sample_loc;

            sample_loc = ci->seek_time/1000 * ci->id3->frequency;
            if (FLAC__seekable_stream_decoder_seek_absolute(flacDecoder, sample_loc)) {
                samplesdone = sample_loc;
                ci->set_elapsed(samplesdone/(ci->id3->frequency/1000));
            }
            ci->seek_time = 0;
        }

        FLAC__seekable_stream_decoder_process_single(flacDecoder);
        FLAC__seekable_stream_decoder_get_decode_position(flacDecoder, &offset);
        ci->set_offset(offset);
    }

    /* Flush the libFLAC buffers */
    FLAC__seekable_stream_decoder_finish(flacDecoder);

    if (ci->request_next_track()) {
        if (stream_info) {
            FLAC__metadata_object_delete(stream_info);
        }
        if (seek_table) {
            FLAC__metadata_object_delete(seek_table);
        }
        metadata_length = 0;
        goto next_track;
    }

    return CODEC_OK;
}
Ejemplo n.º 22
0
FLAC_API FLAC__StreamMetadata *FLAC__metadata_object_clone(const FLAC__StreamMetadata *object)
{
	FLAC__StreamMetadata *to;

	FLAC__ASSERT(0 != object);

	if(0 != (to = FLAC__metadata_object_new(object->type))) {
		to->is_last = object->is_last;
		to->type = object->type;
		to->length = object->length;
		switch(to->type) {
			case FLAC__METADATA_TYPE_STREAMINFO:
				memcpy(&to->data.stream_info, &object->data.stream_info, sizeof(FLAC__StreamMetadata_StreamInfo));
				break;
			case FLAC__METADATA_TYPE_PADDING:
				break;
			case FLAC__METADATA_TYPE_APPLICATION:
				memcpy(&to->data.application.id, &object->data.application.id, FLAC__STREAM_METADATA_APPLICATION_ID_LEN / 8);
				if(!copy_bytes_(&to->data.application.data, object->data.application.data, object->length - FLAC__STREAM_METADATA_APPLICATION_ID_LEN / 8)) {
					FLAC__metadata_object_delete(to);
					return 0;
				}
				break;
			case FLAC__METADATA_TYPE_SEEKTABLE:
				to->data.seek_table.num_points = object->data.seek_table.num_points;
				if(!copy_bytes_((FLAC__byte**)&to->data.seek_table.points, (FLAC__byte*)object->data.seek_table.points, object->data.seek_table.num_points * sizeof(FLAC__StreamMetadata_SeekPoint))) {
					FLAC__metadata_object_delete(to);
					return 0;
				}
				break;
			case FLAC__METADATA_TYPE_VORBIS_COMMENT:
				if(0 != to->data.vorbis_comment.vendor_string.entry) {
					free(to->data.vorbis_comment.vendor_string.entry);
					to->data.vorbis_comment.vendor_string.entry = 0;
				}
				if(!copy_vcentry_(&to->data.vorbis_comment.vendor_string, &object->data.vorbis_comment.vendor_string)) {
					FLAC__metadata_object_delete(to);
					return 0;
				}
				if(object->data.vorbis_comment.num_comments == 0) {
					FLAC__ASSERT(0 == object->data.vorbis_comment.comments);
					to->data.vorbis_comment.comments = 0;
				}
				else {
					FLAC__ASSERT(0 != object->data.vorbis_comment.comments);
					to->data.vorbis_comment.comments = vorbiscomment_entry_array_copy_(object->data.vorbis_comment.comments, object->data.vorbis_comment.num_comments);
					if(0 == to->data.vorbis_comment.comments) {
						FLAC__metadata_object_delete(to);
						return 0;
					}
				}
				to->data.vorbis_comment.num_comments = object->data.vorbis_comment.num_comments;
				break;
			case FLAC__METADATA_TYPE_CUESHEET:
				memcpy(&to->data.cue_sheet, &object->data.cue_sheet, sizeof(FLAC__StreamMetadata_CueSheet));
				if(object->data.cue_sheet.num_tracks == 0) {
					FLAC__ASSERT(0 == object->data.cue_sheet.tracks);
				}
				else {
					FLAC__ASSERT(0 != object->data.cue_sheet.tracks);
					to->data.cue_sheet.tracks = cuesheet_track_array_copy_(object->data.cue_sheet.tracks, object->data.cue_sheet.num_tracks);
					if(0 == to->data.cue_sheet.tracks) {
						FLAC__metadata_object_delete(to);
						return 0;
					}
				}
				break;
			default:
				if(!copy_bytes_(&to->data.unknown.data, object->data.unknown.data, object->length)) {
					FLAC__metadata_object_delete(to);
					return 0;
				}
				break;
		}
	}

	return to;
}
Ejemplo n.º 23
0
FLAC__StreamMetadata *grabbag__picture_parse_specification(const char *spec, const char **error_message)
{
	FLAC__StreamMetadata *obj;
	int state = 0;
	static const char *error_messages[] = {
		"memory allocation error",
		"invalid picture specification",
		"invalid picture specification: can't parse resolution/color part",
		"unable to extract resolution and color info from URL, user must set explicitly",
		"unable to extract resolution and color info from file, user must set explicitly",
		"error opening picture file",
		"error reading picture file",
		"invalid picture type",
		"unable to guess MIME type from file, user must set explicitly",
		"type 1 icon must be a 32x32 pixel PNG"
	};

	FLAC__ASSERT(0 != spec);
	FLAC__ASSERT(0 != error_message);

	/* double protection */
	if(0 == spec)
		return 0;
	if(0 == error_message)
		return 0;

	*error_message = 0;

	if(0 == (obj = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PICTURE))) {
		*error_message = error_messages[0];
		return obj;
	}

	if(strchr(spec, '|')) { /* full format */
		const char *p;
		char *q;
		for(p = spec; *error_message==0 && *p; ) {
			if(*p == '|') {
				switch(state) {
					case 0: /* type */
						if(!local__parse_type_(spec, p-spec, &obj->data.picture))
							*error_message = error_messages[7];
						break;
					case 1: /* mime type */
						if(p-spec) { /* if blank, we'll try to guess later from the picture data */
							if(0 == (q = local__strndup_(spec, p-spec)))
								*error_message = error_messages[0];
							else if(!FLAC__metadata_object_picture_set_mime_type(obj, q, /*copy=*/false))
								*error_message = error_messages[0];
						}
						break;
					case 2: /* description */
						if(0 == (q = local__strndup_(spec, p-spec)))
							*error_message = error_messages[0];
						else if(!FLAC__metadata_object_picture_set_description(obj, (FLAC__byte*)q, /*copy=*/false))
							*error_message = error_messages[0];
						break;
					case 3: /* resolution/color (e.g. [300x300x16[/1234]] */
						if(!local__parse_resolution_(spec, p-spec, &obj->data.picture))
							*error_message = error_messages[2];
						break;
					default:
						*error_message = error_messages[1];
						break;
				}
				p++;
				spec = p;
				state++;
			}
			else
				p++;
		}
	}
	else { /* simple format, filename only, everything else guessed */
		if(!local__parse_type_("", 0, &obj->data.picture)) /* use default picture type */
			*error_message = error_messages[7];
		/* leave MIME type to be filled in later */
		/* leave description empty */
		/* leave the rest to be filled in later: */
		else if(!local__parse_resolution_("", 0, &obj->data.picture))
			*error_message = error_messages[2];
		else
			state = 4;
	}

	/* parse filename, read file, try to extract resolution/color info if needed */
	if(*error_message == 0) {
		if(state != 4)
			*error_message = error_messages[1];
		else { /* 'spec' points to filename/URL */
			if(0 == strcmp(obj->data.picture.mime_type, "-->")) { /* magic MIME type means URL */
				if(!FLAC__metadata_object_picture_set_data(obj, (FLAC__byte*)spec, strlen(spec), /*copy=*/true))
					*error_message = error_messages[0];
				else if(obj->data.picture.width == 0 || obj->data.picture.height == 0 || obj->data.picture.depth == 0)
					*error_message = error_messages[3];
			}
			else { /* regular picture file */
				const FLAC__off_t size = grabbag__file_get_filesize(spec);
				if(size < 0)
					*error_message = error_messages[5];
				else {
					FLAC__byte *buffer = safe_malloc_(size);
					if(0 == buffer)
						*error_message = error_messages[0];
					else {
						FILE *f = flac_fopen(spec, "rb");
						if(0 == f) {
							*error_message = error_messages[5];
							free(buffer);
						}
						else {
							if(fread(buffer, 1, size, f) != (size_t)size)
								*error_message = error_messages[6];
							fclose(f);
							if(0 == *error_message) {
								if(!FLAC__metadata_object_picture_set_data(obj, buffer, size, /*copy=*/false))
									*error_message = error_messages[6];
								/* try to extract MIME type if user left it blank */
								else if(*obj->data.picture.mime_type == '\0' && !local__extract_mime_type_(obj))
									*error_message = error_messages[8];
								/* try to extract resolution/color info if user left it blank */
								else if((obj->data.picture.width == 0 || obj->data.picture.height == 0 || obj->data.picture.depth == 0) && !local__extract_resolution_color_info_(&obj->data.picture))
									*error_message = error_messages[4];
							}
							else {
								free(buffer);
							}
						}
					}
				}
			}
		}
	}

	if(*error_message == 0) {
		if(
			obj->data.picture.type == FLAC__STREAM_METADATA_PICTURE_TYPE_FILE_ICON_STANDARD &&
			(
				(strcmp(obj->data.picture.mime_type, "image/png") && strcmp(obj->data.picture.mime_type, "-->")) ||
				obj->data.picture.width != 32 ||
				obj->data.picture.height != 32
			)
		)
			*error_message = error_messages[9];
	}

	if(*error_message && obj) {
		FLAC__metadata_object_delete(obj);
		obj = 0;
	}

	return obj;
}
Ejemplo n.º 24
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);
}
Ejemplo n.º 25
0
/*
 * Write Flac tag, using the level 2 flac interface
 */
gboolean
flac_tag_write_file_tag (const ET_File *ETFile,
                         GError **error)
{
    const File_Tag *FileTag;
    GFile *file;
    GFileIOStream *iostream;
    EtFlacWriteState state;
    FLAC__IOCallbacks callbacks = { et_flac_read_func, et_flac_write_func,
                                    et_flac_seek_func, et_flac_tell_func,
                                    et_flac_eof_func,
                                    et_flac_write_close_func
                                  };
    const gchar *filename;
    const gchar *filename_utf8;
    const gchar *flac_error_msg;
    FLAC__Metadata_Chain *chain;
    FLAC__Metadata_Iterator *iter;
    FLAC__StreamMetadata_VorbisComment_Entry vce_field_vendor_string; // To save vendor string
    gboolean vce_field_vendor_string_found = FALSE;

    g_return_val_if_fail (ETFile != NULL && ETFile->FileTag != NULL, FALSE);
    g_return_val_if_fail (error == NULL || *error == NULL, FALSE);

    FileTag       = (File_Tag *)ETFile->FileTag->data;
    filename      = ((File_Name *)ETFile->FileNameCur->data)->value;
    filename_utf8 = ((File_Name *)ETFile->FileNameCur->data)->value_utf8;

    /* libFLAC is able to detect (and skip) ID3v2 tags by itself */

    /* Create a new chain instance to get all blocks in one time. */
    chain = FLAC__metadata_chain_new ();

    if (chain == NULL)
    {
        flac_error_msg = FLAC__Metadata_ChainStatusString[FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR];

        g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
                     _("Error while opening file ‘%s’ as FLAC: %s"),
                     filename_utf8, flac_error_msg);
        return FALSE;
    }

    file = g_file_new_for_path (filename);

    state.file = file;
    state.error = NULL;
    /* TODO: Fallback to an in-memory copy of the file for non-local files,
     * where creation of the GFileIOStream may fail. */
    iostream = g_file_open_readwrite (file, NULL, &state.error);

    if (iostream == NULL)
    {
        FLAC__metadata_chain_delete (chain);
        g_propagate_error (error, state.error);
        g_object_unref (file);
        return FALSE;
    }

    state.istream = G_FILE_INPUT_STREAM (g_io_stream_get_input_stream (G_IO_STREAM (iostream)));
    state.ostream = G_FILE_OUTPUT_STREAM (g_io_stream_get_output_stream (G_IO_STREAM (iostream)));
    state.seekable = G_SEEKABLE (iostream);
    state.iostream = iostream;

    if (!FLAC__metadata_chain_read_with_callbacks (chain, &state, callbacks))
    {
        const FLAC__Metadata_ChainStatus status = FLAC__metadata_chain_status (chain);
        flac_error_msg = FLAC__Metadata_ChainStatusString[status];
        FLAC__metadata_chain_delete (chain);

        g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
                     _("Error while opening file ‘%s’ as FLAC: %s"),
                     filename_utf8, flac_error_msg);
        et_flac_write_close_func (&state);
        return FALSE;
    }

    /* Create a new iterator instance for the chain. */
    iter = FLAC__metadata_iterator_new ();

    if (iter == NULL)
    {
        flac_error_msg = FLAC__Metadata_ChainStatusString[FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR];

        g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
                     _("Error while opening file ‘%s’ as FLAC: %s"),
                     filename_utf8, flac_error_msg);
        FLAC__metadata_chain_delete (chain);
        et_flac_write_close_func (&state);
        return FALSE;
    }

    FLAC__metadata_iterator_init (iter, chain);

    while (FLAC__metadata_iterator_next (iter))
    {
        const FLAC__MetadataType block_type = FLAC__metadata_iterator_get_block_type (iter);

        /* TODO: Modify the blocks directly, rather than deleting and
         * recreating. */
        if (block_type == FLAC__METADATA_TYPE_VORBIS_COMMENT)
        {
            // Delete the VORBIS_COMMENT block and convert to padding. But before, save the original vendor string.
            /* Get block data. */
            FLAC__StreamMetadata *block = FLAC__metadata_iterator_get_block(iter);
            FLAC__StreamMetadata_VorbisComment *vc = &block->data.vorbis_comment;

            if (vc->vendor_string.entry != NULL)
            {
                // Get initial vendor string, to don't alterate it by FLAC__VENDOR_STRING when saving file
                vce_field_vendor_string.entry = (FLAC__byte *)g_strdup ((gchar *)vc->vendor_string.entry);
                vce_field_vendor_string.length = strlen ((gchar *)vce_field_vendor_string.entry);
                vce_field_vendor_string_found = TRUE;
            }

            /* Free block data. */
            FLAC__metadata_iterator_delete_block (iter, true);
        }
        else if (block_type == FLAC__METADATA_TYPE_PICTURE)
        {
            /* Delete all the PICTURE blocks, and convert to padding. */
            FLAC__metadata_iterator_delete_block (iter, true);
        }
    }


    //
    // Create and insert a new VORBISCOMMENT block
    //
    {
        FLAC__StreamMetadata *vc_block; // For vorbis comments
        GList *l;

        // Allocate a block for Vorbis comments
        vc_block = FLAC__metadata_object_new(FLAC__METADATA_TYPE_VORBIS_COMMENT);

        // Set the original vendor string, else will be use the version of library
        if (vce_field_vendor_string_found)
        {
            // must set 'copy' param to false, because the API will reuse the  pointer of an empty
            // string (yet still return 'true', indicating it was copied); the string is free'd during
            // metadata_chain_delete routine
            FLAC__metadata_object_vorbiscomment_set_vendor_string(vc_block, vce_field_vendor_string, /*copy=*/false);
        }


        /*********
         * Title *
         *********/
        vc_block_append_tag (vc_block, ET_VORBIS_COMMENT_FIELD_TITLE,
                             FileTag->title,
                             g_settings_get_boolean (MainSettings,
                                     "ogg-split-title"));

        /**********
         * Artist *
         **********/
        vc_block_append_tag (vc_block, ET_VORBIS_COMMENT_FIELD_ARTIST,
                             FileTag->artist,
                             g_settings_get_boolean (MainSettings,
                                     "ogg-split-artist"));

        /****************
         * Album Artist *
         ****************/
        vc_block_append_tag (vc_block, ET_VORBIS_COMMENT_FIELD_ALBUM_ARTIST,
                             FileTag->album_artist,
                             g_settings_get_boolean (MainSettings,
                                     "ogg-split-artist"));

        /*********
         * Album *
         *********/
        vc_block_append_tag (vc_block, ET_VORBIS_COMMENT_FIELD_ALBUM,
                             FileTag->album,
                             g_settings_get_boolean (MainSettings,
                                     "ogg-split-album"));

        /******************************
         * Disc Number and Disc Total *
         ******************************/
        vc_block_append_tag (vc_block, ET_VORBIS_COMMENT_FIELD_DISC_NUMBER,
                             FileTag->disc_number, FALSE);
        vc_block_append_tag (vc_block, ET_VORBIS_COMMENT_FIELD_DISC_TOTAL,
                             FileTag->disc_total, FALSE);

        /********
         * Year *
         ********/
        vc_block_append_tag (vc_block, ET_VORBIS_COMMENT_FIELD_DATE,
                             FileTag->year, FALSE);

        /*************************
         * Track and Total Track *
         *************************/
        vc_block_append_tag (vc_block, ET_VORBIS_COMMENT_FIELD_TRACK_NUMBER,
                             FileTag->track, FALSE);
        vc_block_append_tag (vc_block, ET_VORBIS_COMMENT_FIELD_TRACK_TOTAL,
                             FileTag->track_total, FALSE);

        /*********
         * Genre *
         *********/
        vc_block_append_tag (vc_block, ET_VORBIS_COMMENT_FIELD_GENRE,
                             FileTag->genre,
                             g_settings_get_boolean (MainSettings,
                                     "ogg-split-genre"));

        /***********
         * Comment *
         ***********/
        vc_block_append_tag (vc_block, ET_VORBIS_COMMENT_FIELD_DESCRIPTION,
                             FileTag->comment,
                             g_settings_get_boolean (MainSettings,
                                     "ogg-split-comment"));

        /************
         * Composer *
         ************/
        vc_block_append_tag (vc_block, ET_VORBIS_COMMENT_FIELD_COMPOSER,
                             FileTag->composer,
                             g_settings_get_boolean (MainSettings,
                                     "ogg-split-composer"));

        /*******************
         * Original artist *
         *******************/
        vc_block_append_tag (vc_block, ET_VORBIS_COMMENT_FIELD_PERFORMER,
                             FileTag->orig_artist,
                             g_settings_get_boolean (MainSettings,
                                     "ogg-split-original-artist"));

        /*************
         * Copyright *
         *************/
        vc_block_append_tag (vc_block, ET_VORBIS_COMMENT_FIELD_COPYRIGHT,
                             FileTag->copyright, FALSE);

        /*******
         * URL *
         *******/
        vc_block_append_tag (vc_block, ET_VORBIS_COMMENT_FIELD_CONTACT,
                             FileTag->url, FALSE);

        /**************
         * Encoded by *
         **************/
        vc_block_append_tag (vc_block, ET_VORBIS_COMMENT_FIELD_ENCODED_BY,
                             FileTag->encoded_by, FALSE);


        /**************************
         * Set unsupported fields *
         **************************/
        for (l = FileTag->other; l != NULL; l = g_list_next (l))
        {
            vc_block_append_other_tag (vc_block, (gchar *)l->data);
        }

        // Add the block to the the chain (so we don't need to free the block)
        FLAC__metadata_iterator_insert_block_after(iter, vc_block);
    }



    //
    // Create and insert PICTURE blocks
    //

    /***********
     * Picture *
     ***********/
    {
        EtPicture *pic = FileTag->picture;

        while (pic)
        {
            /* TODO: Can this ever be NULL? */
            if (pic->bytes)
            {
                const gchar *violation;
                FLAC__StreamMetadata *picture_block; // For picture data
                Picture_Format format;
                gconstpointer data;
                gsize data_size;

                // Allocate block for picture data
                picture_block = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PICTURE);

                // Type
                picture_block->data.picture.type = pic->type;

                // Mime type
                format = Picture_Format_From_Data(pic);
                /* Safe to pass a const string, according to the FLAC API
                 * reference. */
                FLAC__metadata_object_picture_set_mime_type(picture_block, (gchar *)Picture_Mime_Type_String(format), TRUE);

                // Description
                if (pic->description)
                {
                    FLAC__metadata_object_picture_set_description(picture_block, (FLAC__byte *)pic->description, TRUE);
                }

                // Resolution
                picture_block->data.picture.width  = pic->width;
                picture_block->data.picture.height = pic->height;
                picture_block->data.picture.depth  = 0;

                /* Picture data. */
                data = g_bytes_get_data (pic->bytes, &data_size);
                /* Safe to pass const data, if the last argument (copy) is
                 * TRUE, according the the FLAC API reference. */
                FLAC__metadata_object_picture_set_data (picture_block,
                                                        (FLAC__byte *)data,
                                                        (FLAC__uint32)data_size,
                                                        true);

                if (!FLAC__metadata_object_picture_is_legal (picture_block,
                        &violation))
                {
                    g_critical ("Created an invalid picture block: ‘%s’",
                                violation);
                    FLAC__metadata_object_delete (picture_block);
                }
                else
                {
                    // Add the block to the the chain (so we don't need to free the block)
                    FLAC__metadata_iterator_insert_block_after(iter, picture_block);
                }
            }

            pic = pic->next;
        }
    }

    FLAC__metadata_iterator_delete (iter);

    //
    // Prepare for writing tag
    //

    FLAC__metadata_chain_sort_padding (chain);

    /* Write tag. */
    if (FLAC__metadata_chain_check_if_tempfile_needed (chain, true))
    {
        EtFlacWriteState temp_state;
        GFile *temp_file;
        GFileIOStream *temp_iostream;
        GError *temp_error = NULL;

        temp_file = g_file_new_tmp ("easytag-XXXXXX", &temp_iostream,
                                    &temp_error);

        if (temp_file == NULL)
        {
            FLAC__metadata_chain_delete (chain);
            g_propagate_error (error, temp_error);
            et_flac_write_close_func (&state);
            return FALSE;
        }

        temp_state.file = temp_file;
        temp_state.error = NULL;
        temp_state.istream = G_FILE_INPUT_STREAM (g_io_stream_get_input_stream (G_IO_STREAM (temp_iostream)));
        temp_state.ostream = G_FILE_OUTPUT_STREAM (g_io_stream_get_output_stream (G_IO_STREAM (temp_iostream)));
        temp_state.seekable = G_SEEKABLE (temp_iostream);
        temp_state.iostream = temp_iostream;

        if (!FLAC__metadata_chain_write_with_callbacks_and_tempfile (chain,
                true,
                &state,
                callbacks,
                &temp_state,
                callbacks))
        {
            const FLAC__Metadata_ChainStatus status = FLAC__metadata_chain_status (chain);
            flac_error_msg = FLAC__Metadata_ChainStatusString[status];

            FLAC__metadata_chain_delete (chain);
            et_flac_write_close_func (&temp_state);
            et_flac_write_close_func (&state);

            g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
                         _("Failed to write comments to file ‘%s’: %s"),
                         filename_utf8, flac_error_msg);
            return FALSE;
        }

        if (!g_file_move (temp_file, file, G_FILE_COPY_OVERWRITE, NULL, NULL,
                          NULL, &state.error))
        {
            FLAC__metadata_chain_delete (chain);
            et_flac_write_close_func (&temp_state);

            g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
                         _("Failed to write comments to file ‘%s’: %s"),
                         filename_utf8, state.error->message);
            et_flac_write_close_func (&state);
            return FALSE;
        }

        et_flac_write_close_func (&temp_state);
    }
    else
    {
        if (!FLAC__metadata_chain_write_with_callbacks (chain, true, &state,
                callbacks))
        {
            const FLAC__Metadata_ChainStatus status = FLAC__metadata_chain_status (chain);
            flac_error_msg = FLAC__Metadata_ChainStatusString[status];

            FLAC__metadata_chain_delete (chain);
            et_flac_write_close_func (&state);

            g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
                         _("Failed to write comments to file ‘%s’: %s"),
                         filename_utf8, flac_error_msg);
            return FALSE;
        }
    }

    FLAC__metadata_chain_delete (chain);
    et_flac_write_close_func (&state);

#ifdef ENABLE_MP3
    {
        // Delete the ID3 tags (create a dummy ETFile for the Id3tag_... function)
        ET_File   *ETFile_tmp    = ET_File_Item_New();
        File_Name *FileName_tmp = et_file_name_new ();
        File_Tag  *FileTag_tmp = et_file_tag_new ();
        // Same file...
        FileName_tmp->value      = g_strdup(filename);
        FileName_tmp->value_utf8 = g_strdup(filename_utf8); // Not necessary to fill 'value_ck'
        ETFile_tmp->FileNameList = g_list_append(NULL,FileName_tmp);
        ETFile_tmp->FileNameCur  = ETFile_tmp->FileNameList;
        // With empty tag...
        ETFile_tmp->FileTagList  = g_list_append(NULL,FileTag_tmp);
        ETFile_tmp->FileTag      = ETFile_tmp->FileTagList;
        id3tag_write_file_tag (ETFile_tmp, NULL);
        ET_Free_File_List_Item(ETFile_tmp);
    }
#endif

    return TRUE;
}
Ejemplo n.º 26
0
FLAC__bool do_shorthand_operation__add_seekpoints(const char *filename, FLAC__Metadata_Chain *chain, const char *specification, FLAC__bool *needs_write)
{
	FLAC__bool ok = true, found_seektable_block = false;
	FLAC__StreamMetadata *block = 0;
	FLAC__Metadata_Iterator *iterator = FLAC__metadata_iterator_new();
	FLAC__uint64 total_samples = 0;
	unsigned sample_rate = 0;

	if(0 == iterator)
		die("out of memory allocating iterator");

	FLAC__metadata_iterator_init(iterator, chain);

	do {
		block = FLAC__metadata_iterator_get_block(iterator);
		if(block->type == FLAC__METADATA_TYPE_STREAMINFO) {
			sample_rate = block->data.stream_info.sample_rate;
			total_samples = block->data.stream_info.total_samples;
		}
		else if(block->type == FLAC__METADATA_TYPE_SEEKTABLE)
			found_seektable_block = true;
	} while(!found_seektable_block && FLAC__metadata_iterator_next(iterator));

	if(total_samples == 0) {
		fprintf(stderr, "%s: ERROR: cannot add seekpoints because STREAMINFO block does not specify total_samples\n", filename);
		return false;
	}

	if(!found_seektable_block) {
		/* create a new block */
		block = FLAC__metadata_object_new(FLAC__METADATA_TYPE_SEEKTABLE);
		if(0 == block)
			die("out of memory allocating SEEKTABLE block");
		while(FLAC__metadata_iterator_prev(iterator))
			;
		if(!FLAC__metadata_iterator_insert_block_after(iterator, block)) {
			print_error_with_chain_status(chain, "%s: ERROR: adding new SEEKTABLE block to metadata", filename);
			FLAC__metadata_object_delete(block);
			return false;
		}
		/* iterator is left pointing to new block */
		FLAC__ASSERT(FLAC__metadata_iterator_get_block(iterator) == block);
	}

	FLAC__metadata_iterator_delete(iterator);

	FLAC__ASSERT(0 != block);
	FLAC__ASSERT(block->type == FLAC__METADATA_TYPE_SEEKTABLE);

	if(!grabbag__seektable_convert_specification_to_template(specification, /*only_explicit_placeholders=*/false, total_samples, sample_rate, block, /*spec_has_real_points=*/0)) {
		fprintf(stderr, "%s: ERROR (internal) preparing seektable with seekpoints\n", filename);
		return false;
	}

	ok = populate_seekpoint_values(filename, block, needs_write);

	if(ok)
		(void) FLAC__format_seektable_sort(&block->data.seek_table);

	return ok;
}
Ejemplo n.º 27
0
CBaseDec::RetCode CFlacDec::Decoder(FILE *in, const int OutputFd, State* const state, CAudioMetaData* meta_data, time_t* const time_played, unsigned int* const secondsToSkip)
{
    int rval;
    //FLAC__uint64 jumptime=0;
    Status = OK;
    mOutputFd = OutputFd;
    mState = state;
    mTimePlayed = time_played;
    mFrameCount = 0;
    mSamplesProcessed = 0;

    mFlacDec = FLAC__stream_decoder_new();

    if (!Open(in, mFlacDec))
    {
        Status=DATA_ERR;
        return Status;
    }

    //test
    //audioDecoder->PrepareClipPlay(frame->header.channels, frame->header.sample_rate, frame->header.bits_per_sample, 1);
    //audioDecoder->PrepareClipPlay(2, 16, 16, 1);

    /* up and away ... */
    mSlotSize = MAX_OUTPUT_SAMPLES * 2 * FLAC__stream_decoder_get_channels(mFlacDec);
    //State oldstate=*state;
    int jumppos=0;
    int actSecsToSkip = (*secondsToSkip != 0) ? *secondsToSkip : MSECS_TO_SKIP / 1000;
    int bytes_to_skip = (int) (1.0 * actSecsToSkip * meta_data->bitrate / 8);
    int bytes_to_play = (int) (1.0 * MSECS_TO_PLAY / 1000 * meta_data->bitrate / 8);
    unsigned int oldSecsToSkip = *secondsToSkip;
    //FLAC__uint64 position;

    do
    {
        while(*state==PAUSE)
            usleep(10000);

        if(*state==FF || *state==REV)
        {
            if (oldSecsToSkip != *secondsToSkip)
            {
                actSecsToSkip = (*secondsToSkip != 0) ? *secondsToSkip : MSECS_TO_SKIP / 1000;
                bytes_to_skip = (int) (1.0 * actSecsToSkip * meta_data->bitrate / 8);
                oldSecsToSkip = *secondsToSkip;
            }
            printf("skipping %d secs and %d bytes\n",actSecsToSkip,bytes_to_skip);
            if(std::abs(ftell(in)-jumppos) > bytes_to_play)
            {
                if(*state==FF)
                {
                    fseek(in, bytes_to_skip, SEEK_CUR);
                    jumppos=ftell(in);
                }
                else
                {
                    if(ftell(in) < bytes_to_skip)
                    {
                        fseek(in, 0, SEEK_SET);
                        *state=PLAY;
                    }
                    else
                    {
                        fseek(in, -bytes_to_skip, SEEK_CUR);
                        jumppos=ftell(in);
                    }
                }
            }

            // if a custom value was set we only jump once
            if (*secondsToSkip != 0)
            {
                *state=PLAY;
            }
        }

        if (FLAC__stream_decoder_get_state(mFlacDec) == FLAC__STREAM_DECODER_END_OF_STREAM)
        {
            rval = false;
            break;
        }

        rval = FLAC__stream_decoder_process_single(mFlacDec);
        // TODO: calculate time_played from the actual file position so that REW/FF actions will be included
        *time_played = (mSamplesProcessed * (mLengthInMsec/1000)) / mTotalSamples;

    } while (rval && *state!=STOP_REQ && Status==OK);

    // let buffer run dry
    printf("let buffer run dry\n");
    while (rval==true && *state!=STOP_REQ && Status==OK /* && mReadSlot != mWriteSlot*/)
    {
        printf("...drying - *state=%x, Status=%x\n", *state, Status);
        usleep(100000);
    }

    if(audioDecoder)
        audioDecoder->StopClip();

    /* clean up the junk from the party */
    if (mMetadata)
        FLAC__metadata_object_delete(mMetadata);
    mMetadata = NULL;
    FLAC__stream_decoder_finish(mFlacDec);
    FLAC__stream_decoder_delete(mFlacDec);
    mFlacDec = NULL;

    /* and drive home ;) */
    return Status;
}
Ejemplo n.º 28
0
Archivo: main.c Proyecto: ACUVE/flac
static FLAC__bool do_picture(const char *prefix)
{
	FLAC__StreamMetadata *obj;
	PictureResolution res;
	const char *error;
	size_t i;

	printf("\n+++ grabbag unit test: picture\n\n");

	/* invalid spec: no filename */
	printf("testing grabbag__picture_parse_specification(\"\")... ");
	if(0 != (obj = grabbag__picture_parse_specification("", &error)))
		return failed_("expected error, got object");
	printf("OK (failed as expected, error: %s)\n", error);

	/* invalid spec: no filename */
	printf("testing grabbag__picture_parse_specification(\"||||\")... ");
	if(0 != (obj = grabbag__picture_parse_specification("||||", &error)))
		return failed_("expected error, got object");
	printf("OK (failed as expected: %s)\n", error);

	/* invalid spec: no filename */
	printf("testing grabbag__picture_parse_specification(\"|image/gif|||\")... ");
	if(0 != (obj = grabbag__picture_parse_specification("|image/gif|||", &error)))
		return failed_("expected error, got object");
	printf("OK (failed as expected: %s)\n", error);

	/* invalid spec: bad resolution */
	printf("testing grabbag__picture_parse_specification(\"|image/gif|desc|320|0.gif\")... ");
	if(0 != (obj = grabbag__picture_parse_specification("|image/gif|desc|320|0.gif", &error)))
		return failed_("expected error, got object");
	printf("OK (failed as expected: %s)\n", error);

	/* invalid spec: bad resolution */
	printf("testing grabbag__picture_parse_specification(\"|image/gif|desc|320x240|0.gif\")... ");
	if(0 != (obj = grabbag__picture_parse_specification("|image/gif|desc|320x240|0.gif", &error)))
		return failed_("expected error, got object");
	printf("OK (failed as expected: %s)\n", error);

	/* invalid spec: no filename */
	printf("testing grabbag__picture_parse_specification(\"|image/gif|desc|320x240x9|\")... ");
	if(0 != (obj = grabbag__picture_parse_specification("|image/gif|desc|320x240x9|", &error)))
		return failed_("expected error, got object");
	printf("OK (failed as expected: %s)\n", error);

	/* invalid spec: #colors exceeds color depth */
	printf("testing grabbag__picture_parse_specification(\"|image/gif|desc|320x240x9/2345|0.gif\")... ");
	if(0 != (obj = grabbag__picture_parse_specification("|image/gif|desc|320x240x9/2345|0.gif", &error)))
		return failed_("expected error, got object");
	printf("OK (failed as expected: %s)\n", error);

	/* invalid spec: standard icon has to be 32x32 PNG */
	printf("testing grabbag__picture_parse_specification(\"1|-->|desc|32x24x9|0.gif\")... ");
	if(0 != (obj = grabbag__picture_parse_specification("1|-->|desc|32x24x9|0.gif", &error)))
		return failed_("expected error, got object");
	printf("OK (failed as expected: %s)\n", error);

	/* invalid spec: need resolution for linked URL */
	printf("testing grabbag__picture_parse_specification(\"|-->|desc||http://blah.blah.blah/z.gif\")... ");
	if(0 != (obj = grabbag__picture_parse_specification("|-->|desc||http://blah.blah.blah/z.gif", &error)))
		return failed_("expected error, got object");
	printf("OK (failed as expected: %s)\n", error);

	printf("testing grabbag__picture_parse_specification(\"|-->|desc|320x240x9|http://blah.blah.blah/z.gif\")... ");
	if(0 == (obj = grabbag__picture_parse_specification("|-->|desc|320x240x9|http://blah.blah.blah/z.gif", &error)))
		return failed_(error);
	printf("OK\n");
	FLAC__metadata_object_delete(obj);

	/* test automatic parsing of picture files from only the file name */
	for(i = 0; i < sizeof(picturefiles)/sizeof(picturefiles[0]); i++)
		if(!test_one_picture(prefix, picturefiles+i, NULL, /*fn_only=*/true))
			return false;

	/* test automatic parsing of picture files to get resolution/color info */
	for(i = 0; i < sizeof(picturefiles)/sizeof(picturefiles[0]); i++)
		if(!test_one_picture(prefix, picturefiles+i, NULL, /*fn_only=*/false))
			return false;

	res.width = picturefiles[0].width = 320;
	res.height = picturefiles[0].height = 240;
	res.depth = picturefiles[0].depth = 3;
	res.colors = picturefiles[0].colors = 2;
	if(!test_one_picture(prefix, picturefiles+0, &res, /*fn_only=*/false))
		return false;

	return true;
}
Ejemplo n.º 29
0
CBaseDec::RetCode CFlacDec::Decoder(FILE *in, const int /*OutputFd*/, State* const state, CAudioMetaData* meta_data, time_t* const time_played, unsigned int* const secondsToSkip)
{
	int rval;
//	FLAC__uint64 jumptime=0;
	Status = OK;
	mState = state;
	mTimePlayed = time_played;
	mFrameCount = 0;
	mSamplesProcessed = 0;
	struct stat s;
	FLAC__uint64 filesize = 0;

	mFlacDec = FLAC__stream_decoder_new();

	if (!Open(in, mFlacDec))
	{
		Status=DATA_ERR;
		return Status;
	}

	if (fstat(fileno(in), &s))
	{
		perror("CFlacDec::Decoder fstat");
		*time_played = 0;
	}
	else
		filesize = (FLAC__uint64)s.st_size;

	/* up and away ... */
	mSlotSize = MAX_OUTPUT_SAMPLES * 2 * FLAC__stream_decoder_get_channels(mFlacDec);
//	State oldstate=*state;
	int jumppos=0;
	int actSecsToSkip = (*secondsToSkip != 0) ? *secondsToSkip : MSECS_TO_SKIP / 1000;
	int bytes_to_skip = actSecsToSkip * meta_data->bitrate / 8;
	int bytes_to_play = MSECS_TO_PLAY * meta_data->bitrate / 8000;
	unsigned int oldSecsToSkip = *secondsToSkip;
	FLAC__uint64 position;

	do
	{
		while(*state==PAUSE)
			usleep(10000);

		if(*state==FF || *state==REV)
		{
			if (oldSecsToSkip != *secondsToSkip)
			{
				actSecsToSkip = (*secondsToSkip != 0) ? *secondsToSkip : MSECS_TO_SKIP / 1000;
				bytes_to_skip = actSecsToSkip * meta_data->bitrate / 8;
				oldSecsToSkip = *secondsToSkip;
			}
			printf("skipping %d secs and %d bytes\n",actSecsToSkip,bytes_to_skip);
			if(std::abs(ftell(in)-jumppos) > bytes_to_play)
			{
				if(*state==FF)
				{
					fseek(in, bytes_to_skip, SEEK_CUR);
					jumppos=ftell(in);
				}
				else
				{
					if(ftell(in) < bytes_to_skip)
					{
						fseek(in, 0, SEEK_SET);
						*state=PLAY;
					}
					else
					{
						fseek(in, -bytes_to_skip, SEEK_CUR);
						jumppos=ftell(in);
					}
				}
			}

			// if a custom value was set we only jump once
			if (*secondsToSkip != 0) {
				*state=PLAY;
			}
		}

		if (FLAC__stream_decoder_get_state(mFlacDec) == FLAC__STREAM_DECODER_END_OF_STREAM) {
			rval = false;
			break;
		}

		rval = FLAC__stream_decoder_process_single(mFlacDec);

		/* update playback position */
		if (filesize > 0 && FLAC__stream_decoder_get_decode_position(mFlacDec, &position))
			*time_played = position / 1000ULL * mLengthInMsec / filesize;

	} while (rval && *state != STOP_REQ && Status == OK);

	// let buffer run dry
	printf("let buffer run dry\n");
	while (rval == true && *state != STOP_REQ && Status == OK /* && mReadSlot != mWriteSlot*/)
	{
		printf("...drying - *state=%x, Status=%x\n", *state, Status);
		usleep(100000);
	}

	/* clean up the junk from the party */
	if (mMetadata)
		FLAC__metadata_object_delete(mMetadata);
	mMetadata = NULL;
	FLAC__stream_decoder_finish(mFlacDec);
	FLAC__stream_decoder_delete(mFlacDec);
	mFlacDec = NULL;

	audioDecoder->StopClip();

	/* and drive home ;) */
	return Status;
}
Ejemplo n.º 30
0
static int
_get_flctags(char *filename, struct song_metadata *psong)
{
	FLAC__Metadata_SimpleIterator *iterator = 0;
	FLAC__StreamMetadata *block;
	int block_number;
	unsigned int sec, ms;
	int i;
	int err = 0;

	if(!(iterator = FLAC__metadata_simple_iterator_new()))
	{
		DPRINTF(E_FATAL, L_SCANNER, "Out of memory while FLAC__metadata_simple_iterator_new()\n");
		return -1;
	}

	block_number = 0;
	if(!FLAC__metadata_simple_iterator_init(iterator, filename, true, true))
	{
		DPRINTF(E_ERROR, L_SCANNER, "Cannot extract tag from %s\n", filename);
		return -1;
	}

	do {
		if(!(block = FLAC__metadata_simple_iterator_get_block(iterator)))
		{
			DPRINTF(E_ERROR, L_SCANNER, "Cannot extract tag from %s\n", filename);
			err = -1;
			goto _exit;
		}

		switch(block->type)
		{
		case FLAC__METADATA_TYPE_STREAMINFO:
			sec = (unsigned int)(block->data.stream_info.total_samples /
			                     block->data.stream_info.sample_rate);
			ms = (unsigned int)(((block->data.stream_info.total_samples %
			                      block->data.stream_info.sample_rate) * 1000) /
			                      block->data.stream_info.sample_rate);
			if ((sec == 0) && (ms == 0))
				break; /* Info is crap, escape div-by-zero. */
			psong->song_length = (sec * 1000) + ms;
			psong->bitrate = (((uint64_t)(psong->file_size) * 1000) / (psong->song_length / 8));
			psong->samplerate = block->data.stream_info.sample_rate;
			psong->channels = block->data.stream_info.channels;
			break;

		case FLAC__METADATA_TYPE_VORBIS_COMMENT:
			for(i = 0; i < block->data.vorbis_comment.num_comments; i++)
			{
				vc_scan(psong,
					(char*)block->data.vorbis_comment.comments[i].entry,
					block->data.vorbis_comment.comments[i].length);
			}
			break;
#if FLAC_API_VERSION_CURRENT >= 10
		case FLAC__METADATA_TYPE_PICTURE:
			psong->image_size = block->data.picture.data_length;
			if((psong->image = malloc(psong->image_size)))
				memcpy(psong->image, block->data.picture.data, psong->image_size);
			else
				DPRINTF(E_ERROR, L_SCANNER, "Out of memory [%s]\n", filename);
			break;
#endif
		default:
			break;
		}
		FLAC__metadata_object_delete(block);
	}
	while(FLAC__metadata_simple_iterator_next(iterator));

 _exit:
	if(iterator)
		FLAC__metadata_simple_iterator_delete(iterator);

	return err;
}