summaryrefslogtreecommitdiff
path: root/plugins/flac
diff options
context:
space:
mode:
authorGravatar Alexey Yakovenko <waker@users.sourceforge.net>2014-06-24 20:41:29 +0200
committerGravatar Alexey Yakovenko <waker@users.sourceforge.net>2014-06-24 20:41:29 +0200
commit40096d01c93b5b6d58b26a183b5cb641277ec52e (patch)
tree5d089d8f3cf5a8c685f04c8c25907b96bc7b3d0a /plugins/flac
parent9c544c03c095115dce261b928334cdf81ae34203 (diff)
flac: added vfs support to read_metadata; fixed reading vorbiscomment metadata block from end of stream
Diffstat (limited to 'plugins/flac')
-rw-r--r--plugins/flac/flac.c77
1 files changed, 69 insertions, 8 deletions
diff --git a/plugins/flac/flac.c b/plugins/flac/flac.c
index fc7bbe5b..71d64f0a 100644
--- a/plugins/flac/flac.c
+++ b/plugins/flac/flac.c
@@ -81,6 +81,8 @@ typedef struct {
const char *fname;
int bitrate;
FLAC__StreamMetadata *flac_cue_sheet;
+
+ int got_vorbis_comments;
} flac_info_t;
// callbacks
@@ -609,6 +611,7 @@ cflac_init_metadata_callback(const FLAC__StreamDecoder *decoder, const FLAC__Str
f |= DDB_TAG_VORBISCOMMENTS;
deadbeef->pl_set_item_flags (it, f);
}
+ info->got_vorbis_comments = 1;
}
else if (metadata->type == FLAC__METADATA_TYPE_CUESHEET) {
if (!info->flac_cue_sheet) {
@@ -691,6 +694,8 @@ cflac_free_temp (DB_fileinfo_t *_info) {
}
}
+static int
+cflac_read_metadata (DB_playItem_t *it);
static DB_playItem_t *
cflac_insert (ddb_playlist_t *plt, DB_playItem_t *after, const char *fname) {
@@ -786,11 +791,12 @@ cflac_insert (ddb_playlist_t *plt, DB_playItem_t *after, const char *fname) {
if (info.info.fmt.samplerate <= 0) {
goto cflac_insert_fail;
}
+ int64_t fsize = deadbeef->fgetlength (info.file);
+ int is_streaming = info.file->vfs->is_streaming ();
deadbeef->pl_add_meta (it, ":FILETYPE", isogg ? "OggFLAC" : "FLAC");
char s[100];
- int64_t fsize = deadbeef->fgetlength (info.file);
snprintf (s, sizeof (s), "%lld", fsize);
deadbeef->pl_add_meta (it, ":FILE_SIZE", s);
snprintf (s, sizeof (s), "%d", info.info.fmt.channels);
@@ -817,6 +823,13 @@ cflac_insert (ddb_playlist_t *plt, DB_playItem_t *after, const char *fname) {
FLAC__stream_decoder_delete(decoder);
decoder = NULL;
+ deadbeef->fclose (info.file);
+ info.file = NULL;
+
+ if (!info.got_vorbis_comments && !is_streaming) {
+ cflac_read_metadata (it);
+ }
+
// try embedded cue
deadbeef->pl_lock ();
if (info.flac_cue_sheet) {
@@ -865,7 +878,43 @@ cflac_insert_fail:
return NULL;
}
-int
+static size_t
+flac_io_read (void *ptr, size_t size, size_t nmemb, FLAC__IOHandle handle) {
+ return deadbeef->fread (ptr, size, nmemb, (DB_FILE *)handle);
+}
+
+static int
+flac_io_seek (FLAC__IOHandle handle, FLAC__int64 offset, int whence) {
+ return deadbeef->fseek ((DB_FILE *)handle, offset, whence);
+}
+
+static FLAC__int64
+flac_io_tell (FLAC__IOHandle handle) {
+ return deadbeef->ftell ((DB_FILE *)handle);
+}
+
+static int
+flac_io_eof (FLAC__IOHandle handle) {
+ int64_t pos = deadbeef->ftell ((DB_FILE *)handle);
+ return pos == deadbeef->fgetlength ((DB_FILE *)handle);
+}
+
+static int
+flac_io_close (FLAC__IOHandle handle) {
+ deadbeef->fclose ((DB_FILE *)handle);
+ return 0;
+}
+
+static FLAC__IOCallbacks iocb = {
+ .read = flac_io_read,
+ .write = NULL,
+ .seek = flac_io_seek,
+ .tell = flac_io_tell,
+ .eof = flac_io_eof,
+ .close = flac_io_close,
+};
+
+static int
cflac_read_metadata (DB_playItem_t *it) {
int err = -1;
FLAC__Metadata_Chain *chain = NULL;
@@ -877,11 +926,17 @@ cflac_read_metadata (DB_playItem_t *it) {
return -1;
}
deadbeef->pl_lock ();
- FLAC__bool res = FLAC__metadata_chain_read (chain, deadbeef->pl_find_meta (it, ":URI"));
+ DB_FILE *file = deadbeef->fopen (deadbeef->pl_find_meta (it, ":URI"));
+ deadbeef->pl_unlock ();
+ if (!file) {
+ return -1;
+ }
+ FLAC__bool res = FLAC__metadata_chain_read_with_callbacks (chain, (FLAC__IOHandle)file, iocb);
if (!res && FLAC__metadata_chain_status(chain) == FLAC__METADATA_SIMPLE_ITERATOR_STATUS_NOT_A_FLAC_FILE) {
- res = FLAC__metadata_chain_read_ogg (chain, deadbeef->pl_find_meta (it, ":URI"));
+ res = FLAC__metadata_chain_read_ogg_with_callbacks (chain, (FLAC__IOHandle)file, iocb);
}
- deadbeef->pl_unlock ();
+ deadbeef->fclose (file);
+ file = NULL;
if (!res) {
trace ("cflac_read_metadata: FLAC__metadata_chain_read(_ogg) failed\n");
goto error;
@@ -968,15 +1023,21 @@ cflac_write_metadata (DB_playItem_t *it) {
return -1;
}
deadbeef->pl_lock ();
- FLAC__bool res = FLAC__metadata_chain_read (chain, deadbeef->pl_find_meta (it, ":URI"));
+ DB_FILE *file = deadbeef->fopen (deadbeef->pl_find_meta (it, ":URI"));
+ deadbeef->pl_unlock ();
+ if (!file) {
+ return -1;
+ }
+ FLAC__bool res = FLAC__metadata_chain_read_with_callbacks (chain, (FLAC__IOHandle)file, iocb);
FLAC__bool isogg = false;
#if USE_OGGEDIT
if (!res && FLAC__metadata_chain_status(chain) == FLAC__METADATA_SIMPLE_ITERATOR_STATUS_NOT_A_FLAC_FILE) {
isogg = true;
- res = FLAC__metadata_chain_read_ogg (chain, deadbeef->pl_find_meta (it, ":URI"));
+ res = FLAC__metadata_chain_read_ogg_with_callbacks (chain, (FLAC__IOHandle)file, iocb);
}
#endif
- deadbeef->pl_unlock ();
+ deadbeef->fclose (file);
+ file = NULL;
if (!res) {
trace ("cflac_write_metadata: FLAC__metadata_chain_read(_ogg) failed - code %d\n", res);
goto error;