aboutsummaryrefslogtreecommitdiffstats
path: root/src/decoder/flac_plugin.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/decoder/flac_plugin.c')
-rw-r--r--src/decoder/flac_plugin.c544
1 files changed, 232 insertions, 312 deletions
diff --git a/src/decoder/flac_plugin.c b/src/decoder/flac_plugin.c
index 0c0d994b7..427d2c4d9 100644
--- a/src/decoder/flac_plugin.c
+++ b/src/decoder/flac_plugin.c
@@ -17,7 +17,14 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
+#include "config.h" /* must be first for large file support */
#include "_flac_common.h"
+#include "flac_compat.h"
+#include "flac_metadata.h"
+
+#if defined(FLAC_API_VERSION_CURRENT) && FLAC_API_VERSION_CURRENT > 7
+#include "_ogg_common.h"
+#endif
#include <glib.h>
@@ -33,8 +40,8 @@
/* this code was based on flac123, from flac-tools */
-static flac_read_status
-flac_read_cb(G_GNUC_UNUSED const flac_decoder *fd,
+static FLAC__StreamDecoderReadStatus
+flac_read_cb(G_GNUC_UNUSED const FLAC__StreamDecoder *fd,
FLAC__byte buf[], flac_read_status_size_t *bytes,
void *fdata)
{
@@ -48,53 +55,59 @@ flac_read_cb(G_GNUC_UNUSED const flac_decoder *fd,
if (r == 0) {
if (decoder_get_command(data->decoder) != DECODE_COMMAND_NONE ||
input_stream_eof(data->input_stream))
- return flac_read_status_eof;
+ return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
else
- return flac_read_status_abort;
+ return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
}
- return flac_read_status_continue;
+ return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
}
-static flac_seek_status
-flac_seek_cb(G_GNUC_UNUSED const flac_decoder *fd,
+static FLAC__StreamDecoderSeekStatus
+flac_seek_cb(G_GNUC_UNUSED const FLAC__StreamDecoder *fd,
FLAC__uint64 offset, void *fdata)
{
struct flac_data *data = (struct flac_data *) fdata;
+ if (!data->input_stream->seekable)
+ return FLAC__STREAM_DECODER_SEEK_STATUS_UNSUPPORTED;
+
if (!input_stream_seek(data->input_stream, offset, SEEK_SET))
- return flac_seek_status_error;
+ return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR;
- return flac_seek_status_ok;
+ return FLAC__STREAM_DECODER_SEEK_STATUS_OK;
}
-static flac_tell_status
-flac_tell_cb(G_GNUC_UNUSED const flac_decoder *fd,
+static FLAC__StreamDecoderTellStatus
+flac_tell_cb(G_GNUC_UNUSED const FLAC__StreamDecoder *fd,
FLAC__uint64 * offset, void *fdata)
{
struct flac_data *data = (struct flac_data *) fdata;
+ if (!data->input_stream->seekable)
+ return FLAC__STREAM_DECODER_SEEK_STATUS_UNSUPPORTED;
+
*offset = (long)(data->input_stream->offset);
- return flac_tell_status_ok;
+ return FLAC__STREAM_DECODER_TELL_STATUS_OK;
}
-static flac_length_status
-flac_length_cb(G_GNUC_UNUSED const flac_decoder *fd,
+static FLAC__StreamDecoderLengthStatus
+flac_length_cb(G_GNUC_UNUSED const FLAC__StreamDecoder *fd,
FLAC__uint64 * length, void *fdata)
{
struct flac_data *data = (struct flac_data *) fdata;
if (data->input_stream->size < 0)
- return flac_length_status_unsupported;
+ return FLAC__STREAM_DECODER_LENGTH_STATUS_UNSUPPORTED;
*length = (size_t) (data->input_stream->size);
- return flac_length_status_ok;
+ return FLAC__STREAM_DECODER_LENGTH_STATUS_OK;
}
static FLAC__bool
-flac_eof_cb(G_GNUC_UNUSED const flac_decoder *fd, void *fdata)
+flac_eof_cb(G_GNUC_UNUSED const FLAC__StreamDecoder *fd, void *fdata)
{
struct flac_data *data = (struct flac_data *) fdata;
@@ -104,7 +117,7 @@ flac_eof_cb(G_GNUC_UNUSED const flac_decoder *fd, void *fdata)
}
static void
-flac_error_cb(G_GNUC_UNUSED const flac_decoder *fd,
+flac_error_cb(G_GNUC_UNUSED const FLAC__StreamDecoder *fd,
FLAC__StreamDecoderErrorStatus status, void *fdata)
{
flac_error_common_cb("flac", status, (struct flac_data *) fdata);
@@ -143,31 +156,6 @@ static void flacPrintErroredState(FLAC__SeekableStreamDecoderState state)
g_warning("%s\n", str);
}
-
-static bool
-flac_init(FLAC__SeekableStreamDecoder *dec,
- FLAC__SeekableStreamDecoderReadCallback read_cb,
- FLAC__SeekableStreamDecoderSeekCallback seek_cb,
- FLAC__SeekableStreamDecoderTellCallback tell_cb,
- FLAC__SeekableStreamDecoderLengthCallback length_cb,
- FLAC__SeekableStreamDecoderEofCallback eof_cb,
- FLAC__SeekableStreamDecoderWriteCallback write_cb,
- FLAC__SeekableStreamDecoderMetadataCallback metadata_cb,
- FLAC__SeekableStreamDecoderErrorCallback error_cb,
- void *data)
-{
- return FLAC__seekable_stream_decoder_set_read_callback(dec, read_cb) &&
- FLAC__seekable_stream_decoder_set_seek_callback(dec, seek_cb) &&
- FLAC__seekable_stream_decoder_set_tell_callback(dec, tell_cb) &&
- FLAC__seekable_stream_decoder_set_length_callback(dec, length_cb) &&
- FLAC__seekable_stream_decoder_set_eof_callback(dec, eof_cb) &&
- FLAC__seekable_stream_decoder_set_write_callback(dec, write_cb) &&
- FLAC__seekable_stream_decoder_set_metadata_callback(dec, metadata_cb) &&
- FLAC__seekable_stream_decoder_set_metadata_respond(dec, FLAC__METADATA_TYPE_VORBIS_COMMENT) &&
- FLAC__seekable_stream_decoder_set_error_callback(dec, error_cb) &&
- FLAC__seekable_stream_decoder_set_client_data(dec, data) &&
- FLAC__seekable_stream_decoder_init(dec) == FLAC__SEEKABLE_STREAM_DECODER_OK;
-}
#else /* FLAC_API_VERSION_CURRENT >= 7 */
static void flacPrintErroredState(FLAC__StreamDecoderState state)
{
@@ -199,35 +187,31 @@ static void flacPrintErroredState(FLAC__StreamDecoderState state)
}
#endif /* FLAC_API_VERSION_CURRENT >= 7 */
-static void flacMetadata(G_GNUC_UNUSED const flac_decoder * dec,
+static void flacMetadata(G_GNUC_UNUSED const FLAC__StreamDecoder * dec,
const FLAC__StreamMetadata * block, void *vdata)
{
flac_metadata_common_cb(block, (struct flac_data *) vdata);
}
static FLAC__StreamDecoderWriteStatus
-flac_write_cb(const flac_decoder *dec, const FLAC__Frame *frame,
+flac_write_cb(const FLAC__StreamDecoder *dec, const FLAC__Frame *frame,
const FLAC__int32 *const buf[], void *vdata)
{
- FLAC__uint32 samples = frame->header.blocksize;
struct flac_data *data = (struct flac_data *) vdata;
- float timeChange;
- FLAC__uint64 newPosition = 0;
-
- timeChange = ((float)samples) / frame->header.sample_rate;
- data->time += timeChange;
-
- flac_get_decode_position(dec, &newPosition);
- if (data->position && newPosition >= data->position) {
- assert(timeChange >= 0);
-
- data->bit_rate =
- ((newPosition - data->position) * 8.0 / timeChange)
- / 1000 + 0.5;
- }
- data->position = newPosition;
+ FLAC__uint64 nbytes = 0;
+
+ if (FLAC__stream_decoder_get_decode_position(dec, &nbytes)) {
+ if (data->position > 0 && nbytes > data->position) {
+ nbytes -= data->position;
+ data->position += nbytes;
+ } else {
+ data->position = nbytes;
+ nbytes = 0;
+ }
+ } else
+ nbytes = 0;
- return flac_common_write(data, frame, buf);
+ return flac_common_write(data, frame, buf, nbytes);
}
static struct tag *
@@ -268,12 +252,8 @@ flac_tag_load(const char *file, const char *char_tnum)
block = FLAC__metadata_simple_iterator_get_block(it);
if (!block)
break;
- if (block->type == FLAC__METADATA_TYPE_VORBIS_COMMENT) {
- flac_vorbis_comments_to_tag(tag, char_tnum, block);
- } else if (block->type == FLAC__METADATA_TYPE_STREAMINFO) {
- tag->time = ((float)block->data.stream_info.total_samples) /
- block->data.stream_info.sample_rate + 0.5;
- }
+
+ flac_tag_apply_metadata(tag, char_tnum, block);
FLAC__metadata_object_delete(block);
} while (FLAC__metadata_simple_iterator_next(it));
@@ -300,6 +280,8 @@ flac_cue_tag_load(const char *file)
FLAC__uint64 track_time = 0;
#ifdef HAVE_CUE /* libcue */
FLAC__StreamMetadata* vc;
+ char* cs_filename;
+ FILE* cs_file;
#endif /* libcue */
FLAC__StreamMetadata* si = FLAC__metadata_object_new(FLAC__METADATA_TYPE_STREAMINFO);
FLAC__StreamMetadata* cs;
@@ -329,16 +311,25 @@ flac_cue_tag_load(const char *file)
FLAC__metadata_object_delete(vc);
}
+
+ if (tag == NULL) {
+ cs_filename = g_strconcat(file, ".cue", NULL);
+
+ cs_file = fopen(cs_filename, "rt");
+ g_free(cs_filename);
+
+ if (cs_file != NULL) {
+ tag = cue_tag_file(cs_file, tnum);
+ fclose(cs_file);
+ }
+ }
#endif /* libcue */
if (tag == NULL)
tag = flac_tag_load(file, char_tnum);
- if (char_tnum != NULL)
- {
- tag_add_item( tag,
- TAG_ITEM_TRACK,
- char_tnum);
+ if (char_tnum != NULL) {
+ tag_add_item(tag, TAG_TRACK, char_tnum);
g_free(char_tnum);
}
@@ -382,105 +373,167 @@ flac_tag_dup(const char *file)
return flac_tag_load(file, NULL);
}
-static void
-flac_decode_internal(struct decoder * decoder,
- struct input_stream *input_stream,
- bool is_ogg)
+/**
+ * Some glue code around FLAC__stream_decoder_new().
+ */
+static FLAC__StreamDecoder *
+flac_decoder_new(void)
{
- flac_decoder *flac_dec;
- struct flac_data data;
- enum decoder_command cmd;
- const char *err = NULL;
-
- if (!(flac_dec = flac_new()))
- return;
- flac_data_init(&data, decoder, input_stream);
- data.tag = tag_new();
+ FLAC__StreamDecoder *sd = FLAC__stream_decoder_new();
+ if (sd == NULL) {
+ g_warning("FLAC__stream_decoder_new() failed");
+ return NULL;
+ }
#if defined(FLAC_API_VERSION_CURRENT) && FLAC_API_VERSION_CURRENT > 7
- if(!FLAC__stream_decoder_set_metadata_respond(flac_dec, FLAC__METADATA_TYPE_VORBIS_COMMENT))
- {
- g_debug("Failed to set metadata respond\n");
- }
+ if(!FLAC__stream_decoder_set_metadata_respond(sd, FLAC__METADATA_TYPE_VORBIS_COMMENT))
+ g_debug("FLAC__stream_decoder_set_metadata_respond() has failed");
#endif
- if (is_ogg) {
- if (!flac_ogg_init(flac_dec, flac_read_cb,
- flac_seek_cb, flac_tell_cb,
- flac_length_cb, flac_eof_cb,
- flac_write_cb, flacMetadata,
- flac_error_cb, (void *)&data)) {
- err = "doing Ogg init()";
- goto fail;
- }
- } else {
- if (!flac_init(flac_dec, flac_read_cb,
- flac_seek_cb, flac_tell_cb,
- flac_length_cb, flac_eof_cb,
- flac_write_cb, flacMetadata,
- flac_error_cb, (void *)&data)) {
- err = "doing init()";
- goto fail;
- }
- }
+ return sd;
+}
- if (!flac_process_metadata(flac_dec)) {
- err = "problem reading metadata";
- goto fail;
- }
+static bool
+flac_decoder_initialize(struct flac_data *data, FLAC__StreamDecoder *sd,
+ bool seekable, FLAC__uint64 duration)
+{
+ struct audio_format audio_format;
- if (!audio_format_valid(&data.audio_format)) {
- g_warning("Invalid audio format: %u:%u:%u\n",
- data.audio_format.sample_rate,
- data.audio_format.bits,
- data.audio_format.channels);
- goto fail;
+ if (!FLAC__stream_decoder_process_until_end_of_metadata(sd)) {
+ g_warning("problem reading metadata");
+ return false;
}
- decoder_initialized(decoder, &data.audio_format,
- input_stream->seekable, data.total_time);
+ if (!flac_data_get_audio_format(data, &audio_format))
+ return false;
+
+ if (duration == 0)
+ duration = data->stream_info.total_samples;
+
+ decoder_initialized(data->decoder, &audio_format,
+ seekable,
+ (float)duration /
+ (float)data->stream_info.sample_rate);
+ return true;
+}
+
+static void
+flac_decoder_loop(struct flac_data *data, FLAC__StreamDecoder *flac_dec,
+ FLAC__uint64 t_start, FLAC__uint64 t_end)
+{
+ struct decoder *decoder = data->decoder;
+ enum decoder_command cmd;
+
+ data->first_frame = t_start;
while (true) {
- if (!tag_is_empty(data.tag)) {
- cmd = decoder_tag(decoder, input_stream, data.tag);
- tag_free(data.tag);
- data.tag = tag_new();
+ if (data->tag != NULL && !tag_is_empty(data->tag)) {
+ cmd = decoder_tag(data->decoder, data->input_stream,
+ data->tag);
+ tag_free(data->tag);
+ data->tag = tag_new();
} else
cmd = decoder_get_command(decoder);
if (cmd == DECODE_COMMAND_SEEK) {
- FLAC__uint64 seek_sample = decoder_seek_where(decoder) *
- data.audio_format.sample_rate + 0.5;
- if (flac_seek_absolute(flac_dec, seek_sample)) {
- data.time = ((float)seek_sample) /
- data.audio_format.sample_rate;
- data.position = 0;
+ FLAC__uint64 seek_sample = t_start +
+ decoder_seek_where(decoder) *
+ data->stream_info.sample_rate;
+ if (seek_sample >= t_start &&
+ (t_end == 0 || seek_sample <= t_end) &&
+ FLAC__stream_decoder_seek_absolute(flac_dec, seek_sample)) {
+ data->next_frame = seek_sample;
+ data->position = 0;
decoder_command_finished(decoder);
} else
decoder_seek_error(decoder);
} else if (cmd == DECODE_COMMAND_STOP ||
- flac_get_state(flac_dec) == flac_decoder_eof)
+ FLAC__stream_decoder_get_state(flac_dec) == FLAC__STREAM_DECODER_END_OF_STREAM)
break;
- if (!flac_process_single(flac_dec)) {
+ if (t_end != 0 && data->next_frame >= t_end)
+ /* end of this sub track */
+ break;
+
+ if (!FLAC__stream_decoder_process_single(flac_dec)) {
cmd = decoder_get_command(decoder);
if (cmd != DECODE_COMMAND_SEEK)
break;
}
}
+
if (cmd != DECODE_COMMAND_STOP) {
- flacPrintErroredState(flac_get_state(flac_dec));
- flac_finish(flac_dec);
+ flacPrintErroredState(FLAC__stream_decoder_get_state(flac_dec));
+ FLAC__stream_decoder_finish(flac_dec);
}
+}
-fail:
- if (data.replay_gain_info)
- replay_gain_info_free(data.replay_gain_info);
+static void
+flac_decode_internal(struct decoder * decoder,
+ struct input_stream *input_stream,
+ bool is_ogg)
+{
+ FLAC__StreamDecoder *flac_dec;
+ struct flac_data data;
+ const char *err = NULL;
+
+ flac_dec = flac_decoder_new();
+ if (flac_dec == NULL)
+ return;
+
+ flac_data_init(&data, decoder, input_stream);
+ data.tag = tag_new();
+
+ if (is_ogg) {
+#if defined(FLAC_API_VERSION_CURRENT) && FLAC_API_VERSION_CURRENT > 7
+ FLAC__StreamDecoderInitStatus status =
+ FLAC__stream_decoder_init_ogg_stream(flac_dec,
+ flac_read_cb,
+ flac_seek_cb,
+ flac_tell_cb,
+ flac_length_cb,
+ flac_eof_cb,
+ flac_write_cb,
+ flacMetadata,
+ flac_error_cb,
+ (void *)&data);
+ if (status != FLAC__STREAM_DECODER_INIT_STATUS_OK) {
+ err = "doing Ogg init()";
+ goto fail;
+ }
+#else
+ goto fail;
+#endif
+ } else {
+ FLAC__StreamDecoderInitStatus status =
+ FLAC__stream_decoder_init_stream(flac_dec,
+ flac_read_cb,
+ flac_seek_cb,
+ flac_tell_cb,
+ flac_length_cb,
+ flac_eof_cb,
+ flac_write_cb,
+ flacMetadata,
+ flac_error_cb,
+ (void *)&data);
+ if (status != FLAC__STREAM_DECODER_INIT_STATUS_OK) {
+ err = "doing init()";
+ goto fail;
+ }
+ }
- tag_free(data.tag);
+ if (!flac_decoder_initialize(&data, flac_dec,
+ input_stream->seekable, 0)) {
+ flac_data_deinit(&data);
+ FLAC__stream_decoder_delete(flac_dec);
+ return;
+ }
- if (flac_dec)
- flac_delete(flac_dec);
+ flac_decoder_loop(&data, flac_dec, 0, 0);
+
+fail:
+ flac_data_deinit(&data);
+ FLAC__stream_decoder_delete(flac_dec);
if (err)
g_warning("%s\n", err);
@@ -509,7 +562,8 @@ flac_container_decode(struct decoder* decoder,
FLAC__uint64 track_time = 0;
FLAC__StreamMetadata* cs = NULL;
- flac_decoder *flac_dec;
+ FLAC__StreamDecoder *flac_dec;
+ FLAC__StreamDecoderInitStatus init_status;
struct flac_data data;
const char *err = NULL;
@@ -542,122 +596,43 @@ flac_container_decode(struct decoder* decoder,
return;
}
- if (!(flac_dec = flac_new()))
- {
- g_free(pathname);
+ flac_dec = flac_decoder_new();
+ if (flac_dec == NULL)
return;
- }
flac_data_init(&data, decoder, NULL);
-#if defined(FLAC_API_VERSION_CURRENT) && FLAC_API_VERSION_CURRENT > 7
- if(!FLAC__stream_decoder_set_metadata_respond(flac_dec, FLAC__METADATA_TYPE_VORBIS_COMMENT))
- {
- g_debug("Failed to set metadata respond\n");
- }
-#endif
-
-
- if (is_ogg)
- {
- if (FLAC__stream_decoder_init_ogg_file( flac_dec,
- pathname,
- flac_write_cb,
- flacMetadata,
- flac_error_cb,
- (void*) &data )
- != FLAC__STREAM_DECODER_INIT_STATUS_OK )
- {
- err = "doing Ogg init()";
- goto fail;
- }
- }
- else
- {
- if (FLAC__stream_decoder_init_file( flac_dec,
- pathname,
- flac_write_cb,
- flacMetadata,
- flac_error_cb,
- (void*) &data )
- != FLAC__STREAM_DECODER_INIT_STATUS_OK )
- {
- err = "doing init()";
- goto fail;
- }
- }
-
- if (!flac_process_metadata(flac_dec))
- {
- err = "problem reading metadata";
+ init_status = is_ogg
+ ? FLAC__stream_decoder_init_ogg_file(flac_dec, pathname,
+ flac_write_cb,
+ flacMetadata,
+ flac_error_cb,
+ &data)
+ : FLAC__stream_decoder_init_file(flac_dec,
+ pathname, flac_write_cb,
+ flacMetadata, flac_error_cb,
+ &data);
+ g_free(pathname);
+ if (init_status != FLAC__STREAM_DECODER_INIT_STATUS_OK) {
+ err = "doing init()";
goto fail;
}
- if (!audio_format_valid(&data.audio_format))
- {
- g_warning("Invalid audio format: %u:%u:%u\n",
- data.audio_format.sample_rate,
- data.audio_format.bits,
- data.audio_format.channels);
- goto fail;
+ if (!flac_decoder_initialize(&data, flac_dec, true, track_time)) {
+ flac_data_deinit(&data);
+ FLAC__stream_decoder_delete(flac_dec);
+ return;
}
- // set track time (order is important: after stream init)
- data.total_time = ((float)track_time / (float)data.audio_format.sample_rate);
- data.position = 0;
-
- decoder_initialized(decoder, &data.audio_format,
- true, data.total_time);
-
// seek to song start (order is important: after decoder init)
- flac_seek_absolute(flac_dec, (FLAC__uint64)t_start);
-
- while (true)
- {
- if (!flac_process_single(flac_dec))
- break;
-
- // we only need to break at the end of track if we are in "cue mode"
- if (data.time >= data.total_time)
- {
- flacPrintErroredState(flac_get_state(flac_dec));
- flac_finish(flac_dec);
- }
-
- if (decoder_get_command(decoder) == DECODE_COMMAND_SEEK)
- {
- FLAC__uint64 seek_sample = t_start +
- (decoder_seek_where(decoder) * data.audio_format.sample_rate);
-
- if (seek_sample >= t_start && seek_sample <= t_end &&
- flac_seek_absolute(flac_dec, (FLAC__uint64)seek_sample)) {
- data.time = (float)(seek_sample - t_start) /
- data.audio_format.sample_rate;
- data.position = 0;
+ FLAC__stream_decoder_seek_absolute(flac_dec, (FLAC__uint64)t_start);
+ data.next_frame = t_start;
- decoder_command_finished(decoder);
- } else
- decoder_seek_error(decoder);
- }
- else if (flac_get_state(flac_dec) == flac_decoder_eof)
- break;
- }
-
- if (decoder_get_command(decoder) != DECODE_COMMAND_STOP)
- {
- flacPrintErroredState(flac_get_state(flac_dec));
- flac_finish(flac_dec);
- }
+ flac_decoder_loop(&data, flac_dec, t_start, t_end);
fail:
- if (pathname)
- g_free(pathname);
-
- if (data.replay_gain_info)
- replay_gain_info_free(data.replay_gain_info);
-
- if (flac_dec)
- flac_delete(flac_dec);
+ flac_data_deinit(&data);
+ FLAC__stream_decoder_delete(flac_dec);
if (err)
g_warning("%s\n", err);
@@ -672,24 +647,17 @@ flac_filedecode_internal(struct decoder* decoder,
const char* fname,
bool is_ogg)
{
- flac_decoder *flac_dec;
+ FLAC__StreamDecoder *flac_dec;
struct flac_data data;
const char *err = NULL;
unsigned int flac_err_state = 0;
- if (!(flac_dec = flac_new()))
+ flac_dec = flac_decoder_new();
+ if (flac_dec == NULL)
return;
flac_data_init(&data, decoder, NULL);
-#if defined(FLAC_API_VERSION_CURRENT) && FLAC_API_VERSION_CURRENT > 7
- if(!FLAC__stream_decoder_set_metadata_respond(flac_dec, FLAC__METADATA_TYPE_VORBIS_COMMENT))
- {
- g_debug("Failed to set metadata respond\n");
- }
-#endif
-
-
if (is_ogg)
{
if ( (flac_err_state = FLAC__stream_decoder_init_ogg_file( flac_dec,
@@ -727,60 +695,17 @@ flac_filedecode_internal(struct decoder* decoder,
}
}
- if (!flac_process_metadata(flac_dec))
- {
- err = "problem reading metadata";
- goto fail;
- }
-
- if (!audio_format_valid(&data.audio_format))
- {
- g_warning("Invalid audio format: %u:%u:%u\n",
- data.audio_format.sample_rate,
- data.audio_format.bits,
- data.audio_format.channels);
- goto fail;
- }
-
- decoder_initialized(decoder, &data.audio_format,
- true, data.total_time);
-
- while (true)
- {
- if (!flac_process_single(flac_dec))
- break;
-
- if (decoder_get_command(decoder) == DECODE_COMMAND_SEEK)
- {
- FLAC__uint64 seek_sample = decoder_seek_where(decoder) *
- data.audio_format.sample_rate + 0.5;
- if (flac_seek_absolute(flac_dec, seek_sample))
- {
- data.time = ((float)seek_sample) /
- data.audio_format.sample_rate;
- data.position = 0;
- decoder_command_finished(decoder);
- }
- else
- decoder_seek_error(decoder);
-
- }
- else if (flac_get_state(flac_dec) == flac_decoder_eof)
- break;
+ if (!flac_decoder_initialize(&data, flac_dec, true, 0)) {
+ flac_data_deinit(&data);
+ FLAC__stream_decoder_delete(flac_dec);
+ return;
}
- if (decoder_get_command(decoder) != DECODE_COMMAND_STOP)
- {
- flacPrintErroredState(flac_get_state(flac_dec));
- flac_finish(flac_dec);
- }
+ flac_decoder_loop(&data, flac_dec, 0, 0);
fail:
- if (data.replay_gain_info)
- replay_gain_info_free(data.replay_gain_info);
-
- if (flac_dec)
- flac_delete(flac_dec);
+ flac_data_deinit(&data);
+ FLAC__stream_decoder_delete(flac_dec);
if (err)
g_warning("%s\n", err);
@@ -836,13 +761,8 @@ oggflac_tag_dup(const char *file)
do {
if (!(block = FLAC__metadata_iterator_get_block(it)))
break;
- if (block->type == FLAC__METADATA_TYPE_VORBIS_COMMENT) {
- flac_vorbis_comments_to_tag(ret, NULL, block);
- } else if (block->type == FLAC__METADATA_TYPE_STREAMINFO) {
- ret->time = ((float)block->data.stream_info.
- total_samples) /
- block->data.stream_info.sample_rate + 0.5;
- }
+
+ flac_tag_apply_metadata(ret, NULL, block);
} while (FLAC__metadata_iterator_next(it));
FLAC__metadata_iterator_delete(it);