summaryrefslogtreecommitdiff
path: root/plugins
diff options
context:
space:
mode:
authorGravatar Alexey Yakovenko <wakeroid@gmail.com>2009-09-28 22:56:57 +0200
committerGravatar Alexey Yakovenko <wakeroid@gmail.com>2009-09-28 22:56:57 +0200
commitb5bedb49dad2da3aab4a997ac6daad1c4f30d67a (patch)
tree82390feb2bc4925b707f11f65e08f7523e9dad90 /plugins
parent75d630d07d325ca8ac895dc23186819c00003926 (diff)
added VFS plugins
implemented stdio VFS plugin ported flac, mpgmad, ffap, vorbis, wavpack, junklib to VFS
Diffstat (limited to 'plugins')
-rw-r--r--plugins/ffap/ffap.c53
-rw-r--r--plugins/flac/flac.c160
-rw-r--r--plugins/mpgmad/mpgmad.c102
-rw-r--r--plugins/vorbis/vorbis.c48
-rw-r--r--plugins/wavpack/wavpack.c94
5 files changed, 316 insertions, 141 deletions
diff --git a/plugins/ffap/ffap.c b/plugins/ffap/ffap.c
index 68899578..735630bf 100644
--- a/plugins/ffap/ffap.c
+++ b/plugins/ffap/ffap.c
@@ -268,15 +268,14 @@ typedef struct APEContext {
} APEContext;
APEContext ape_ctx;
-FILE *fp;
inline static int
-read_uint16(FILE *fp, uint16_t* x)
+read_uint16(DB_FILE *fp, uint16_t* x)
{
unsigned char tmp[2];
int n;
- n = fread(tmp, 1, 2, fp);
+ n = deadbeef->fread(tmp, 1, 2, fp);
if (n != 2)
return -1;
@@ -288,18 +287,18 @@ read_uint16(FILE *fp, uint16_t* x)
inline static int
-read_int16(FILE *fp, int16_t* x)
+read_int16(DB_FILE *fp, int16_t* x)
{
return read_uint16(fp, (uint16_t*)x);
}
inline static int
-read_uint32(FILE *fp, uint32_t* x)
+read_uint32(DB_FILE *fp, uint32_t* x)
{
unsigned char tmp[4];
int n;
- n = fread(tmp, 1, 4, fp);
+ n = deadbeef->fread(tmp, 1, 4, fp);
if (n != 4)
return -1;
@@ -365,7 +364,7 @@ static void ape_dumpinfo(APEContext * ape_ctx)
}
static int
-ape_read_header(FILE *fp, APEContext *ape)
+ape_read_header(DB_FILE *fp, APEContext *ape)
{
int i;
int total_blocks;
@@ -373,7 +372,7 @@ ape_read_header(FILE *fp, APEContext *ape)
/* TODO: Skip any leading junk such as id3v2 tags */
ape->junklength = 0;
- if (fread (ape->magic, 1, 4, fp) != 4) {
+ if (deadbeef->fread (ape->magic, 1, 4, fp) != 4) {
return -1;
}
if (memcmp (ape->magic, "MAC ", 4))
@@ -413,14 +412,14 @@ ape_read_header(FILE *fp, APEContext *ape)
if (read_uint32 (fp, &ape->wavtaillength) < 0) {
return -1;
}
- if (fread (ape->md5, 1, 16, fp) != 16) {
+ if (deadbeef->fread (ape->md5, 1, 16, fp) != 16) {
return -1;
}
/* Skip any unknown bytes at the end of the descriptor.
This is for future compatibility */
if (ape->descriptorlength > 52) {
- fseek (fp, ape->descriptorlength - 52, SEEK_CUR);
+ deadbeef->fseek (fp, ape->descriptorlength - 52, SEEK_CUR);
}
/* Read header data */
@@ -478,7 +477,7 @@ ape_read_header(FILE *fp, APEContext *ape)
}
if (ape->formatflags & MAC_FORMAT_FLAG_HAS_PEAK_LEVEL) {
- fseek(fp, 4, SEEK_CUR); /* Skip the peak level */
+ deadbeef->fseek(fp, 4, SEEK_CUR); /* Skip the peak level */
ape->headerlength += 4;
}
@@ -507,7 +506,7 @@ ape_read_header(FILE *fp, APEContext *ape)
/* Skip any stored wav header */
if (!(ape->formatflags & MAC_FORMAT_FLAG_CREATE_WAV_HEADER)) {
- fseek (fp, ape->wavheaderlength, SEEK_CUR);
+ deadbeef->fseek (fp, ape->wavheaderlength, SEEK_CUR);
}
}
@@ -583,19 +582,19 @@ static inline const uint32_t bswap_32(uint32_t x)
return x;
}
-static int ape_read_packet(FILE *fp, APEContext *ape_ctx)
+static int ape_read_packet(DB_FILE *fp, APEContext *ape_ctx)
{
int ret;
int nblocks;
APEContext *ape = ape_ctx;
uint32_t extra_size = 8;
- if (feof(fp))
- return -1;
if (ape->currentframe > ape->totalframes)
return -1;
// fprintf (stderr, "seeking to %d\n", ape->frames[ape->currentframe].pos);
- fseek (fp, ape->frames[ape->currentframe].pos, SEEK_SET);
+ if (deadbeef->fseek (fp, ape->frames[ape->currentframe].pos, SEEK_SET) != 0) {
+ return -1;
+ }
/* Calculate how many blocks there are in this frame */
if (ape->currentframe == (ape->totalframes - 1))
@@ -615,7 +614,7 @@ static int ape_read_packet(FILE *fp, APEContext *ape_ctx)
int sz = PACKET_BUFFER_SIZE-8;
sz = min (sz, ape->frames[ape->currentframe].size);
// fprintf (stderr, "readsize: %d, packetsize: %d\n", sz, ape->frames[ape->currentframe].size);
- ret = fread (ape->packet_data + extra_size, 1, sz, fp);
+ ret = deadbeef->fread (ape->packet_data + extra_size, 1, sz, fp);
ape->packet_sizeleft = ape->frames[ape->currentframe].size - sz + 8;
ape->packet_remaining = sz+8;
@@ -664,10 +663,12 @@ static int ape_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp
}
#endif
+static DB_FILE *fp;
+
static int
ffap_init(DB_playItem_t *it)
{
- fp = fopen (it->fname, "rb");
+ fp = deadbeef->fopen (it->fname);
if (!fp) {
return -1;
}
@@ -1548,7 +1549,7 @@ ape_decode_frame(APEContext *s, void *data, int *data_size)
sz = min (sz, s->packet_sizeleft);
sz = sz&~3;
uint8_t *p = s->packet_data + s->packet_remaining;
- int r = fread (p, 1, sz, fp);
+ int r = deadbeef->fread (p, 1, sz, fp);
//if (r != s) {
// fprintf (stderr, "unexpected eof while reading ape frame\n");
// return -1;
@@ -1626,19 +1627,19 @@ static DB_playItem_t *
ffap_insert (DB_playItem_t *after, const char *fname) {
APEContext ape_ctx;
memset (&ape_ctx, 0, sizeof (ape_ctx));
- FILE *fp = fopen (fname, "rb");
+ DB_FILE *fp = deadbeef->fopen (fname);
if (!fp) {
return NULL;
}
if (ape_read_header (fp, &ape_ctx) < 0) {
fprintf (stderr, "failed to read ape header\n");
- fclose (fp);
+ deadbeef->fclose (fp);
ape_free_ctx (&ape_ctx);
return NULL;
}
if ((ape_ctx.fileversion < APE_MIN_VERSION) || (ape_ctx.fileversion > APE_MAX_VERSION)) {
fprintf(stderr, "unsupported file version - %.2f\n", ape_ctx.fileversion/1000.0);
- fclose (fp);
+ deadbeef->fclose (fp);
ape_free_ctx (&ape_ctx);
return NULL;
}
@@ -1647,7 +1648,7 @@ ffap_insert (DB_playItem_t *after, const char *fname) {
DB_playItem_t *it;
it = deadbeef->pl_insert_cue (after, fname, &plugin, "APE", ape_ctx.totalsamples, ape_ctx.samplerate);
if (it) {
- fclose (fp);
+ deadbeef->fclose (fp);
ape_free_ctx (&ape_ctx);
return it;
}
@@ -1661,16 +1662,16 @@ ffap_insert (DB_playItem_t *after, const char *fname) {
int v2err = deadbeef->junk_read_id3v2 (it, fp);
int v1err = deadbeef->junk_read_id3v1 (it, fp);
if (v1err >= 0) {
- fseek (fp, -128, SEEK_END);
+ deadbeef->fseek (fp, -128, SEEK_END);
}
else {
- fseek (fp, 0, SEEK_END);
+ deadbeef->fseek (fp, 0, SEEK_END);
}
int apeerr = deadbeef->junk_read_ape (it, fp);
deadbeef->pl_add_meta (it, "title", NULL);
after = deadbeef->pl_insert_item (after, it);
- fclose (fp);
+ deadbeef->fclose (fp);
ape_free_ctx (&ape_ctx);
return after;
}
diff --git a/plugins/flac/flac.c b/plugins/flac/flac.c
index aebe061e..a2e8506a 100644
--- a/plugins/flac/flac.c
+++ b/plugins/flac/flac.c
@@ -24,8 +24,8 @@
static DB_decoder_t plugin;
static DB_functions_t *deadbeef;
-//#define trace(...) { fprintf(stderr, __VA_ARGS__); }
-#define trace(fmt,...)
+#define trace(...) { fprintf(stderr, __VA_ARGS__); }
+//#define trace(fmt,...)
#define min(x,y) ((x)<(y)?(x):(y))
#define max(x,y) ((x)>(y)?(x):(y))
@@ -39,8 +39,10 @@ static int endsample;
static int currentsample;
typedef struct {
+ DB_FILE *file;
DB_playItem_t *after;
DB_playItem_t *last;
+ DB_playItem_t *it;
const char *fname;
int samplerate;
int channels;
@@ -48,6 +50,45 @@ typedef struct {
int bps;
} cue_cb_data_t;
+static cue_cb_data_t flac_callbacks;
+
+// callbacks
+FLAC__StreamDecoderReadStatus flac_read_cb (const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], size_t *bytes, void *client_data) {
+ cue_cb_data_t *cb = (cue_cb_data_t *)client_data;
+ size_t r = deadbeef->fread (buffer, 1, *bytes, cb->file);
+ *bytes = r;
+ if (r == 0) {
+ return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
+ }
+ return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
+}
+
+FLAC__StreamDecoderSeekStatus flac_seek_cb (const FLAC__StreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data) {
+ cue_cb_data_t *cb = (cue_cb_data_t *)client_data;
+ int r = deadbeef->fseek (cb->file, absolute_byte_offset, SEEK_SET);
+ return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
+}
+
+FLAC__StreamDecoderTellStatus flac_tell_cb (const FLAC__StreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data) {
+ cue_cb_data_t *cb = (cue_cb_data_t *)client_data;
+ size_t r = deadbeef->ftell (cb->file);
+ *absolute_byte_offset = r;
+ return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
+}
+
+FLAC__StreamDecoderLengthStatus flac_lenght_cb (const FLAC__StreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data) {
+ cue_cb_data_t *cb = (cue_cb_data_t *)client_data;
+ size_t pos = deadbeef->ftell (cb->file);
+ deadbeef->fseek (cb->file, 0, SEEK_END);
+ *stream_length = deadbeef->ftell (cb->file);
+ deadbeef->fseek (cb->file, pos, SEEK_SET);
+ return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
+}
+
+FLAC__bool flac_eof_cb (const FLAC__StreamDecoder *decoder, void *client_data) {
+ return 0;
+}
+
static FLAC__StreamDecoderWriteStatus
cflac_write_callback (const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const inputbuffer[], void *client_data) {
if (frame->header.blocksize == 0) {
@@ -73,7 +114,7 @@ cflac_write_callback (const FLAC__StreamDecoder *decoder, const FLAC__Frame *fra
}
}
if (readbytes > bufsize) {
- fprintf (stderr, "flac: buffer overflow, distortion will occur\n");
+ trace ("flac: buffer overflow, distortion will occur\n");
// return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
}
return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
@@ -101,70 +142,66 @@ cflac_init_error_callback(const FLAC__StreamDecoder *decoder, FLAC__StreamDecode
cflac_init_stop_decoding = 1;
}
-static void
-cflac_free (void);
-
static int
cflac_init (DB_playItem_t *it) {
- FILE *fp = fopen (it->fname, "rb");
- if (!fp) {
+ memset (&flac_callbacks, 0, sizeof (flac_callbacks));
+ flac_callbacks.file = deadbeef->fopen (it->fname);
+ if (!flac_callbacks.file) {
return -1;
}
- int skip = deadbeef->junk_get_leading_size (fp);
+ int skip = deadbeef->junk_get_leading_size (flac_callbacks.file);
if (skip > 0) {
- fseek (fp, skip, SEEK_SET);
+ deadbeef->fseek (flac_callbacks.file, skip, SEEK_SET);
}
char sign[4];
- if (fread (sign, 1, 4, fp) != 4) {
- fclose (fp);
+ if (deadbeef->fread (sign, 1, 4, flac_callbacks.file) != 4) {
+ plugin.free ();
return -1;
}
if (strncmp (sign, "fLaC", 4)) {
- fclose (fp);
+ plugin.free ();
return -1;
}
- fclose (fp);
- fp = NULL;
+ deadbeef->fseek (flac_callbacks.file, -4, SEEK_CUR);
FLAC__StreamDecoderInitStatus status;
decoder = FLAC__stream_decoder_new();
if (!decoder) {
-// printf ("FLAC__stream_decoder_new failed\n");
+ trace ("FLAC__stream_decoder_new failed\n");
return -1;
}
FLAC__stream_decoder_set_md5_checking(decoder, 0);
- cue_cb_data_t cb;
- status = FLAC__stream_decoder_init_file(decoder, it->fname, cflac_write_callback, cflac_metadata_callback, cflac_error_callback, &cb);
+ status = FLAC__stream_decoder_init_stream (decoder, flac_read_cb, flac_seek_cb, flac_tell_cb, flac_lenght_cb, flac_eof_cb, cflac_write_callback, cflac_metadata_callback, cflac_error_callback, &flac_callbacks);
if (status != FLAC__STREAM_DECODER_INIT_STATUS_OK) {
- cflac_free ();
+ plugin.free ();
return -1;
}
//plugin.info.samplerate = -1;
if (!FLAC__stream_decoder_process_until_end_of_metadata (decoder)) {
- cflac_free ();
+ plugin.free ();
return -1;
}
- plugin.info.samplerate = cb.samplerate;
- plugin.info.channels = cb.channels;
- plugin.info.bps = cb.bps;
+ plugin.info.samplerate = flac_callbacks.samplerate;
+ plugin.info.channels = flac_callbacks.channels;
+ plugin.info.bps = flac_callbacks.bps;
plugin.info.readpos = 0;
if (plugin.info.samplerate == -1) { // not a FLAC stream
- cflac_free ();
+ plugin.free ();
return -1;
}
if (it->endsample > 0) {
startsample = it->startsample;
endsample = it->endsample;
if (plugin.seek_sample (0) < 0) {
- cflac_free ();
+ plugin.free ();
return -1;
}
}
else {
startsample = 0;
- endsample = cb.totalsamples-1;
+ endsample = flac_callbacks.totalsamples-1;
currentsample = 0;
- trace ("startsample=%d, endsample=%d, totalsamples=%d\n", startsample, endsample, cb.totalsamples);
+ trace ("startsample=%d, endsample=%d, totalsamples=%d\n", startsample, endsample, flac_callbacks.totalsamples);
}
remaining = 0;
@@ -287,16 +324,19 @@ cflac_init_write_callback (const FLAC__StreamDecoder *decoder, const FLAC__Frame
static void
cflac_init_cue_metadata_callback(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data) {
if (cflac_init_stop_decoding) {
+ trace ("flac: cflac_init_cue_metadata_callback: cflac_init_stop_decoding=1\n");
return;
}
cue_cb_data_t *cb = (cue_cb_data_t *)client_data;
if (metadata->type == FLAC__METADATA_TYPE_STREAMINFO) {
+ trace ("flac: cflac_init_cue_metadata_callback: got FLAC__METADATA_TYPE_STREAMINFO\n");
cb->samplerate = metadata->data.stream_info.sample_rate;
cb->channels = metadata->data.stream_info.channels;
//cb->duration = metadata->data.stream_info.total_samples / (float)metadata->data.stream_info.sample_rate;
cb->totalsamples = metadata->data.stream_info.total_samples;
}
else if (metadata->type == FLAC__METADATA_TYPE_VORBIS_COMMENT) {
+ trace ("flac: cflac_init_cue_metadata_callback: got FLAC__METADATA_TYPE_VORBIS_COMMENT\n");
const FLAC__StreamMetadata_VorbisComment *vc = &metadata->data.vorbis_comment;
for (int i = 0; i < vc->num_comments; i++) {
const FLAC__StreamMetadata_VorbisComment_Entry *c = &vc->comments[i];
@@ -315,10 +355,11 @@ cflac_init_cue_metadata_callback(const FLAC__StreamDecoder *decoder, const FLAC_
static void
cflac_init_metadata_callback(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data) {
if (cflac_init_stop_decoding) {
- fprintf (stderr, "error flag is set, ignoring init_metadata callback..\n");
+ trace ("error flag is set, ignoring init_metadata callback..\n");
return;
}
- DB_playItem_t *it = (DB_playItem_t *)client_data;
+ cue_cb_data_t *cb = (cue_cb_data_t *)client_data;
+ DB_playItem_t *it = cb->it;
//it->tracknum = 0;
if (metadata->type == FLAC__METADATA_TYPE_STREAMINFO) {
it->duration = metadata->data.stream_info.total_samples / (float)metadata->data.stream_info.sample_rate;
@@ -380,64 +421,80 @@ cflac_init_metadata_callback(const FLAC__StreamDecoder *decoder, const FLAC__Str
static DB_playItem_t *
cflac_insert (DB_playItem_t *after, const char *fname) {
+ trace ("flac: inserting %s\n", fname);
DB_playItem_t *it = NULL;
FLAC__StreamDecoder *decoder = NULL;
- FILE *fp = fopen (fname, "rb");
- if (!fp) {
+ cue_cb_data_t cb = {
+ .fname = fname,
+ .after = after,
+ .last = after
+ };
+ cb.file = deadbeef->fopen (fname);
+ if (!cb.file) {
goto cflac_insert_fail;
}
// skip id3 junk
- int skip = deadbeef->junk_get_leading_size (fp);
+ int skip = deadbeef->junk_get_leading_size (cb.file);
if (skip > 0) {
- fseek (fp, skip, SEEK_SET);
+ deadbeef->fseek (cb.file, skip, SEEK_SET);
}
char sign[4];
- if (fread (sign, 1, 4, fp) != 4) {
+ if (deadbeef->fread (sign, 1, 4, cb.file) != 4) {
+ trace ("flac: failed to read signature\n");
goto cflac_insert_fail;
}
if (strncmp (sign, "fLaC", 4)) {
+ trace ("flac: file signature is not fLaC\n");
goto cflac_insert_fail;
}
- fclose (fp);
- fp = NULL;
+ deadbeef->fseek (cb.file, -4, SEEK_CUR);
cflac_init_stop_decoding = 0;
//try embedded cue, and calculate duration
FLAC__StreamDecoderInitStatus status;
decoder = FLAC__stream_decoder_new();
if (!decoder) {
+ trace ("flac: failed to create decoder\n");
goto cflac_insert_fail;
}
FLAC__stream_decoder_set_md5_checking(decoder, 0);
// try embedded cue
- cue_cb_data_t cb = {
- .fname = fname,
- .after = after,
- .last = after
- };
FLAC__stream_decoder_set_metadata_respond_all (decoder);
- status = FLAC__stream_decoder_init_file (decoder, fname, cflac_init_write_callback, cflac_init_cue_metadata_callback, cflac_init_error_callback, &cb);
+ status = FLAC__stream_decoder_init_stream (decoder, flac_read_cb, flac_seek_cb, flac_tell_cb, flac_lenght_cb, flac_eof_cb, cflac_init_write_callback, cflac_init_cue_metadata_callback, cflac_init_error_callback, &cb);
if (status != FLAC__STREAM_DECODER_INIT_STATUS_OK || cflac_init_stop_decoding) {
+ trace ("flac: FLAC__stream_decoder_init_stream failed\n");
goto cflac_insert_fail;
}
if (!FLAC__stream_decoder_process_until_end_of_metadata (decoder) || cflac_init_stop_decoding) {
+ trace ("flac: FLAC__stream_decoder_process_until_end_of_metadata failed\n");
goto cflac_insert_fail;
}
FLAC__stream_decoder_delete(decoder);
decoder = NULL;
if (cb.last != after) {
+ trace ("flac: loaded embedded cuesheet\n");
// that means embedded cue is loaded
+ if (cb.file) {
+ deadbeef->fclose (cb.file);
+ }
return cb.last;
}
// try external cue
DB_playItem_t *cue_after = deadbeef->pl_insert_cue (after, fname, &plugin, "flac", cb.totalsamples, cb.samplerate);
if (cue_after) {
+ if (cb.file) {
+ deadbeef->fclose (cb.file);
+ }
+ trace ("flac: loaded external cuesheet\n");
return cue_after;
}
decoder = FLAC__stream_decoder_new();
if (!decoder) {
+ if (cb.file) {
+ deadbeef->fclose (cb.file);
+ }
goto cflac_insert_fail;
}
FLAC__stream_decoder_set_md5_checking(decoder, 0);
@@ -447,17 +504,30 @@ cflac_insert (DB_playItem_t *after, const char *fname) {
it = deadbeef->pl_item_alloc ();
it->decoder = &plugin;
it->fname = strdup (fname);
- status = FLAC__stream_decoder_init_file (decoder, fname, cflac_init_write_callback, cflac_init_metadata_callback, cflac_init_error_callback, it);
+ cb.it = it;
+ if (skip > 0) {
+ deadbeef->fseek (cb.file, skip, SEEK_SET);
+ }
+ else {
+ deadbeef->rewind (cb.file);
+ }
+ deadbeef->fseek (cb.file, -4, SEEK_CUR);
+ status = FLAC__stream_decoder_init_stream (decoder, flac_read_cb, flac_seek_cb, flac_tell_cb, flac_lenght_cb, flac_eof_cb, cflac_init_write_callback, cflac_init_metadata_callback, cflac_init_error_callback, &cb);
if (status != FLAC__STREAM_DECODER_INIT_STATUS_OK || cflac_init_stop_decoding) {
+ trace ("flac: FLAC__stream_decoder_init_stream [2] failed\n");
goto cflac_insert_fail;
}
if (!FLAC__stream_decoder_process_until_end_of_metadata (decoder) || cflac_init_stop_decoding) {
+ trace ("flac: FLAC__stream_decoder_process_until_end_of_metadata [2] failed\n");
goto cflac_insert_fail;
}
FLAC__stream_decoder_delete(decoder);
decoder = NULL;
it->filetype = "FLAC";
after = deadbeef->pl_insert_item (after, it);
+ if (cb.file) {
+ deadbeef->fclose (cb.file);
+ }
return after;
cflac_insert_fail:
if (it) {
@@ -466,8 +536,8 @@ cflac_insert_fail:
if (decoder) {
FLAC__stream_decoder_delete(decoder);
}
- if (fp) {
- fclose (fp);
+ if (cb.file) {
+ deadbeef->fclose (cb.file);
}
return NULL;
}
diff --git a/plugins/mpgmad/mpgmad.c b/plugins/mpgmad/mpgmad.c
index 99279faf..14a277f0 100644
--- a/plugins/mpgmad/mpgmad.c
+++ b/plugins/mpgmad/mpgmad.c
@@ -54,7 +54,7 @@ static DB_functions_t *deadbeef;
#define VBR_SCALE_FLAG 0x0008
typedef struct {
- FILE *file;
+ DB_FILE *file;
// // input buffer, for MPEG data
// // FIXME: this should go away if reading happens per-frame
@@ -181,8 +181,8 @@ cmp3_scan_stream (buffer_t *buffer, int sample) {
for (;;) {
uint32_t hdr;
uint8_t sync;
- size_t pos = ftell (buffer->file);
- if (fread (&sync, 1, 1, buffer->file) != 1) {
+ size_t pos = deadbeef->ftell (buffer->file);
+ if (deadbeef->fread (&sync, 1, 1, buffer->file) != 1) {
break; // eof
}
if (sync != 0xff) {
@@ -190,7 +190,7 @@ cmp3_scan_stream (buffer_t *buffer, int sample) {
}
else {
// 2nd sync byte
- if (fread (&sync, 1, 1, buffer->file) != 1) {
+ if (deadbeef->fread (&sync, 1, 1, buffer->file) != 1) {
break; // eof
}
if ((sync >> 5) != 7) {
@@ -200,11 +200,11 @@ cmp3_scan_stream (buffer_t *buffer, int sample) {
// found frame
hdr = (0xff<<24) | (sync << 16);
// read 2 bytes more
- if (fread (&sync, 1, 1, buffer->file) != 1) {
+ if (deadbeef->fread (&sync, 1, 1, buffer->file) != 1) {
break; // eof
}
hdr |= sync << 8;
- if (fread (&sync, 1, 1, buffer->file) != 1) {
+ if (deadbeef->fread (&sync, 1, 1, buffer->file) != 1) {
break; // eof
}
hdr |= sync;
@@ -333,22 +333,22 @@ cmp3_scan_stream (buffer_t *buffer, int sample) {
// try to read xing/info tag (only on initial scans)
if (sample <= 0 && !got_xing_header)
{
- size_t framepos = ftell (buffer->file);
+ size_t framepos = deadbeef->ftell (buffer->file);
trace ("trying to read xing header\n");
if (ver == 1) {
- fseek (buffer->file, 32, SEEK_CUR);
+ deadbeef->fseek (buffer->file, 32, SEEK_CUR);
}
else {
- fseek (buffer->file, 17, SEEK_CUR);
+ deadbeef->fseek (buffer->file, 17, SEEK_CUR);
}
const char xing[] = "Xing";
const char info[] = "Info";
char magic[4];
- if (fread (magic, 1, 4, buffer->file) != 4) {
+ if (deadbeef->fread (magic, 1, 4, buffer->file) != 4) {
return -1; // EOF
}
// add information to skip this frame
- int startoffset = ftell (buffer->file) + packetlength;
+ int startoffset = deadbeef->ftell (buffer->file) + packetlength;
if (startoffset > buffer->startoffset) {
buffer->startoffset = startoffset;
}
@@ -358,13 +358,13 @@ cmp3_scan_stream (buffer_t *buffer, int sample) {
// read flags
uint32_t flags;
uint8_t buf[4];
- if (fread (buf, 1, 4, buffer->file) != 4) {
+ if (deadbeef->fread (buf, 1, 4, buffer->file) != 4) {
return -1; // EOF
}
flags = extract_i32 (buf);
if (flags & FRAMES_FLAG) {
// read number of frames
- if (fread (buf, 1, 4, buffer->file) != 4) {
+ if (deadbeef->fread (buf, 1, 4, buffer->file) != 4) {
return -1; // EOF
}
uint32_t nframes = extract_i32 (buf);
@@ -374,65 +374,65 @@ cmp3_scan_stream (buffer_t *buffer, int sample) {
buffer->samplerate = samplerate;
}
if (flags & BYTES_FLAG) {
- fseek (buffer->file, 4, SEEK_CUR);
+ deadbeef->fseek (buffer->file, 4, SEEK_CUR);
}
if (flags & TOC_FLAG) {
- fseek (buffer->file, 100, SEEK_CUR);
+ deadbeef->fseek (buffer->file, 100, SEEK_CUR);
}
if (flags & VBR_SCALE_FLAG) {
- fseek (buffer->file, 4, SEEK_CUR);
+ deadbeef->fseek (buffer->file, 4, SEEK_CUR);
}
// lame header
- if (fread (buf, 1, 4, buffer->file) != 4) {
+ if (deadbeef->fread (buf, 1, 4, buffer->file) != 4) {
return -1; // EOF
}
- trace ("tell=%x, %c%c%c%c\n", ftell(buffer->file), buf[0], buf[1], buf[2], buf[3]);
+ trace ("tell=%x, %c%c%c%c\n", deadbeef->ftell(buffer->file), buf[0], buf[1], buf[2], buf[3]);
if (!memcmp (buf, "LAME", 4)) {
trace ("lame header found\n");
- fseek (buffer->file, 6, SEEK_CUR);
+ deadbeef->fseek (buffer->file, 6, SEEK_CUR);
// FIXME: that can be optimized by single read
uint8_t lpf;
- fread (&lpf, 1, 1, buffer->file);
+ deadbeef->fread (&lpf, 1, 1, buffer->file);
//3 floats: replay gain
- fread (buf, 1, 4, buffer->file);
+ deadbeef->fread (buf, 1, 4, buffer->file);
float rg_peaksignalamp = extract_f32 (buf);
- fread (buf, 1, 2, buffer->file);
+ deadbeef->fread (buf, 1, 2, buffer->file);
uint16_t rg_radio = extract_i16 (buf);
- fread (buf, 1, 2, buffer->file);
+ deadbeef->fread (buf, 1, 2, buffer->file);
uint16_t rg_audiophile = extract_i16 (buf);
// skip
- fseek (buffer->file, 2, SEEK_CUR);
- fread (buf, 1, 3, buffer->file);
+ deadbeef->fseek (buffer->file, 2, SEEK_CUR);
+ deadbeef->fread (buf, 1, 3, buffer->file);
uint32_t startdelay = (((uint32_t)buf[0]) << 4) | ((((uint32_t)buf[1]) & 0xf0)>>4);
uint32_t enddelay = ((((uint32_t)buf[1])&0x0f)<<8) | ((uint32_t)buf[2]);
// skip
- fseek (buffer->file, 1, SEEK_CUR);
+ deadbeef->fseek (buffer->file, 1, SEEK_CUR);
// mp3gain
uint8_t mp3gain;
- fread (&mp3gain, 1, 1, buffer->file);
+ deadbeef->fread (&mp3gain, 1, 1, buffer->file);
// skip
- fseek (buffer->file, 2, SEEK_CUR);
+ deadbeef->fseek (buffer->file, 2, SEEK_CUR);
// musiclen
- fread (buf, 1, 4, buffer->file);
+ deadbeef->fread (buf, 1, 4, buffer->file);
uint32_t musiclen = extract_i32 (buf);
trace ("lpf: %d, peaksignalamp: %f, radiogain: %d, audiophile: %d, startdelay: %d, enddelay: %d, mp3gain: %d, musiclen: %d\n", lpf, rg_peaksignalamp, rg_radio, rg_audiophile, startdelay, enddelay, mp3gain, musiclen);
// skip crc
- //fseek (buffer->file, 4, SEEK_CUR);
+ //deadbeef->fseek (buffer->file, 4, SEEK_CUR);
buffer->startdelay = startdelay;
buffer->enddelay = enddelay;
}
if (sample <= 0 && (flags&FRAMES_FLAG)) {
buffer->totalsamples -= buffer->enddelay;
trace ("lame totalsamples: %d\n", buffer->totalsamples);
- fseek (buffer->file, framepos+packetlength-4, SEEK_SET);
+ deadbeef->fseek (buffer->file, framepos+packetlength-4, SEEK_SET);
return 0;
}
}
if (sample == 0) {
// xing header failed, calculate based on file size
- fseek (buffer->file, 0, SEEK_END);
- int sz = ftell (buffer->file) - buffer->startoffset - buffer->endoffset;
+ deadbeef->fseek (buffer->file, 0, SEEK_END);
+ int sz = deadbeef->ftell (buffer->file) - buffer->startoffset - buffer->endoffset;
int nframes = sz / packetlength;
buffer->duration = nframes * samples_per_frame / samplerate;
buffer->totalsamples = nframes * samples_per_frame;
@@ -440,16 +440,16 @@ cmp3_scan_stream (buffer_t *buffer, int sample) {
// trace ("packetlength=%d, fsize=%d, nframes=%d, samples_per_frame=%d, samplerate=%d, duration=%f, totalsamples=%d\n", packetlength, sz, nframes, samples_per_frame, samplerate, buffer->duration, buffer->totalsamples);
if (sample == 0) {
- fseek (buffer->file, framepos+packetlength-4, SEEK_SET);
+ deadbeef->fseek (buffer->file, framepos+packetlength-4, SEEK_SET);
return 0;
}
}
- fseek (buffer->file, framepos+packetlength-4, SEEK_SET);
+ deadbeef->fseek (buffer->file, framepos+packetlength-4, SEEK_SET);
got_xing_header = 1;
}
if (sample >= 0 && scansamples + samples_per_frame >= sample) {
- fseek (buffer->file, -4, SEEK_CUR);
+ deadbeef->fseek (buffer->file, -4, SEEK_CUR);
buffer->currentsample = sample;
buffer->skipsamples = sample - scansamples;
return 0;
@@ -459,7 +459,7 @@ cmp3_scan_stream (buffer_t *buffer, int sample) {
buffer->duration += dur;
nframe++;
if (packetlength > 0) {
- fseek (buffer->file, packetlength-4, SEEK_CUR);
+ deadbeef->fseek (buffer->file, packetlength-4, SEEK_CUR);
}
}
if (nframe == 0) {
@@ -474,13 +474,13 @@ cmp3_scan_stream (buffer_t *buffer, int sample) {
static int
cmp3_init (DB_playItem_t *it) {
memset (&buffer, 0, sizeof (buffer));
- buffer.file = fopen (it->fname, "rb");
+ buffer.file = deadbeef->fopen (it->fname);
if (!buffer.file) {
return -1;
}
int skip = deadbeef->junk_get_leading_size (buffer.file);
if (skip > 0) {
- fseek(buffer.file, skip, SEEK_SET);
+ deadbeef->fseek(buffer.file, skip, SEEK_SET);
}
plugin.info.readpos = 0;
cmp3_scan_stream (&buffer, -1); // scan entire stream, calc duration
@@ -496,11 +496,11 @@ cmp3_init (DB_playItem_t *it) {
buffer.endsample = buffer.totalsamples-1;
buffer.skipsamples = buffer.startdelay;
buffer.currentsample = buffer.startdelay;
- fseek (buffer.file, buffer.startoffset, SEEK_SET);
+ deadbeef->fseek (buffer.file, buffer.startoffset, SEEK_SET);
}
if (buffer.samplerate == 0) {
trace ("bad mpeg file: %f\n", it->fname);
- fclose (buffer.file);
+ deadbeef->fclose (buffer.file);
return -1;
}
plugin.info.bps = buffer.bitspersample;
@@ -584,7 +584,7 @@ cmp3_decode (void) {
int size = READBUFFER - buffer.remaining;
int bytesread = 0;
char *bytes = buffer.input + buffer.remaining;
- bytesread = fread (bytes, 1, size, buffer.file);
+ bytesread = deadbeef->fread (bytes, 1, size, buffer.file);
if (!bytesread) {
// add guard
eof = 1;
@@ -686,7 +686,7 @@ cmp3_decode (void) {
static void
cmp3_free (void) {
if (buffer.file) {
- fclose (buffer.file);
+ deadbeef->fclose (buffer.file);
buffer.file = NULL;
mad_synth_finish (&synth);
mad_frame_finish (&frame);
@@ -788,10 +788,10 @@ cmp3_seek_sample (int sample) {
return -1; // eof
}
// restart file, and load until we hit required pos
- fseek (buffer.file, 0, SEEK_SET);
+ deadbeef->fseek (buffer.file, 0, SEEK_SET);
int skip = deadbeef->junk_get_leading_size (buffer.file);
if (skip > 0) {
- fseek(buffer.file, skip, SEEK_SET);
+ deadbeef->fseek(buffer.file, skip, SEEK_SET);
}
mad_synth_finish (&synth);
mad_frame_finish (&frame);
@@ -832,7 +832,7 @@ static const char *filetypes[] = {
static DB_playItem_t *
cmp3_insert (DB_playItem_t *after, const char *fname) {
- FILE *fp = fopen (fname, "rb");
+ DB_FILE *fp = deadbeef->fopen (fname);
if (!fp) {
return NULL;
}
@@ -841,12 +841,12 @@ cmp3_insert (DB_playItem_t *after, const char *fname) {
buffer.file = fp;
int skip = deadbeef->junk_get_leading_size (buffer.file);
if (skip > 0) {
- fseek(buffer.file, skip, SEEK_SET);
+ deadbeef->fseek(buffer.file, skip, SEEK_SET);
}
// calc approx. mp3 duration
int res = cmp3_scan_stream (&buffer, 0);
if (res < 0) {
- fclose (fp);
+ deadbeef->fclose (fp);
return NULL;
}
@@ -893,11 +893,11 @@ cmp3_insert (DB_playItem_t *after, const char *fname) {
// FIXME! bad numsamples passed to cue
DB_playItem_t *cue_after = deadbeef->pl_insert_cue (after, fname, &plugin, ftype, buffer.duration*buffer.samplerate, buffer.samplerate);
if (cue_after) {
- fclose (fp);
+ deadbeef->fclose (fp);
return cue_after;
}
- rewind (fp);
+ deadbeef->rewind (fp);
DB_playItem_t *it = deadbeef->pl_item_alloc ();
it->decoder = &plugin;
@@ -906,7 +906,7 @@ cmp3_insert (DB_playItem_t *after, const char *fname) {
int apeerr = deadbeef->junk_read_ape (it, fp);
int v2err = deadbeef->junk_read_id3v2 (it, fp);
int v1err = deadbeef->junk_read_id3v1 (it, fp);
- fclose (fp);
+ deadbeef->fclose (fp);
deadbeef->pl_add_meta (it, "title", NULL);
it->duration = buffer.duration;
it->filetype = ftype;
diff --git a/plugins/vorbis/vorbis.c b/plugins/vorbis/vorbis.c
index 26cd3051..32d99660 100644
--- a/plugins/vorbis/vorbis.c
+++ b/plugins/vorbis/vorbis.c
@@ -18,7 +18,6 @@
#include <vorbis/codec.h>
#include <vorbis/vorbisfile.h>
#include <string.h>
-#include <stdio.h>
#include <stdlib.h>
#ifdef HAVE_CONFIG_H
# include <config.h>
@@ -34,7 +33,7 @@
static DB_decoder_t plugin;
static DB_functions_t *deadbeef;
-static FILE *file;
+static DB_FILE *file;
static OggVorbis_File vorbis_file;
static vorbis_info *vi;
static int cur_bit_stream;
@@ -45,19 +44,48 @@ static int currentsample;
static void
cvorbis_free (void);
+static size_t
+cvorbis_fread (void *ptr, size_t size, size_t nmemb, void *datasource) {
+ return deadbeef->fread (ptr, size, nmemb, datasource);
+}
+
+static int
+cvorbis_fseek (void *datasource, ogg_int64_t offset, int whence) {
+ DB_FILE *f = (DB_FILE *)datasource;
+ return deadbeef->fseek (datasource, offset, whence);
+}
+
+static int
+cvorbis_fclose (void *datasource) {
+ deadbeef->fclose (datasource);
+ return 0;
+}
+
+static long
+cvorbis_ftell (void *datasource) {
+ return deadbeef->ftell (datasource);
+}
+
static int
cvorbis_init (DB_playItem_t *it) {
file = NULL;
vi = NULL;
cur_bit_stream = -1;
- file = fopen (it->fname, "rb");
+ file = deadbeef->fopen (it->fname);
if (!file) {
return -1;
}
+ ov_callbacks ovcb = {
+ .read_func = cvorbis_fread,
+ .seek_func = cvorbis_fseek,
+ .close_func = cvorbis_fclose,
+ .tell_func = cvorbis_ftell
+ };
memset (&plugin.info, 0, sizeof (plugin.info));
- ov_open (file, &vorbis_file, NULL, 0);
+
+ ov_open_callbacks (file, &vorbis_file, NULL, 0, ovcb);
vi = ov_info (&vorbis_file, -1);
if (!vi) { // not a vorbis stream
cvorbis_free ();
@@ -156,15 +184,23 @@ cvorbis_seek (float time) {
static DB_playItem_t *
cvorbis_insert (DB_playItem_t *after, const char *fname) {
// check for validity
- FILE *fp = fopen (fname, "rb");
+ DB_FILE *fp = deadbeef->fopen (fname);
if (!fp) {
+ fprintf (stderr, "vorbis: failed to fopen %s\n", fname);
return NULL;
}
+ ov_callbacks ovcb = {
+ .read_func = cvorbis_fread,
+ .seek_func = cvorbis_fseek,
+ .close_func = cvorbis_fclose,
+ .tell_func = cvorbis_ftell
+ };
OggVorbis_File vorbis_file;
vorbis_info *vi;
- ov_open (fp, &vorbis_file, NULL, 0);
+ ov_open_callbacks (fp, &vorbis_file, NULL, 0, ovcb);
vi = ov_info (&vorbis_file, -1);
if (!vi) { // not a vorbis stream
+ fprintf (stderr, "vorbis: failed to ov_open %s\n", fname);
return NULL;
}
float duration = ov_time_total (&vorbis_file, -1);
diff --git a/plugins/wavpack/wavpack.c b/plugins/wavpack/wavpack.c
index 5a9b9501..876fc0d3 100644
--- a/plugins/wavpack/wavpack.c
+++ b/plugins/wavpack/wavpack.c
@@ -19,6 +19,7 @@
#include <string.h>
#include <wavpack/wavpack.h>
+#include <stdio.h>
#include "../../deadbeef.h"
#define min(x,y) ((x)<(y)?(x):(y))
@@ -31,6 +32,7 @@ static DB_decoder_t plugin;
static DB_functions_t *deadbeef;
typedef struct {
+ DB_FILE *file;
WavpackContext *ctx;
int startsample;
int endsample;
@@ -38,11 +40,68 @@ typedef struct {
static wvctx_t wvctx;
+int32_t wv_read_bytes(void *id, void *data, int32_t bcount) {
+ trace ("wv_read_bytes\n");
+ return deadbeef->fread (data, 1, bcount, id);
+}
+
+uint32_t wv_get_pos(void *id) {
+ trace ("wv_get_pos\n");
+ return deadbeef->ftell (id);
+}
+
+int wv_set_pos_abs(void *id, uint32_t pos) {
+ trace ("wv_set_pos_abs\n");
+ return deadbeef->fseek (id, pos, SEEK_SET);
+}
+int wv_set_pos_rel(void *id, int32_t delta, int mode) {
+ trace ("wv_set_pos_rel\n");
+ return deadbeef->fseek (id, delta, SEEK_CUR);
+}
+int wv_push_back_byte(void *id, int c) {
+ trace ("wv_push_back_byte\n");
+ deadbeef->fseek (id, -1, SEEK_CUR);
+ return deadbeef->ftell (id);
+}
+uint32_t wv_get_length(void *id) {
+ trace ("wv_get_length\n");
+ size_t pos = deadbeef->ftell (id);
+ deadbeef->fseek (id, 0, SEEK_END);
+ size_t sz = deadbeef->ftell (id);
+ deadbeef->fseek (id, pos, SEEK_SET);
+ return sz;
+}
+int wv_can_seek(void *id) {
+ trace ("wv_can_seek\n");
+ return 1;
+}
+
+int32_t wv_write_bytes (void *id, void *data, int32_t bcount) {
+ return 0;
+}
+
+static WavpackStreamReader wsr = {
+ .read_bytes = wv_read_bytes,
+ .get_pos = wv_get_pos,
+ .set_pos_abs = wv_set_pos_abs,
+ .set_pos_rel = wv_set_pos_rel,
+ .push_back_byte = wv_push_back_byte,
+ .get_length = wv_get_length,
+ .can_seek = wv_can_seek,
+ .write_bytes = wv_write_bytes
+};
+
static int
wv_init (DB_playItem_t *it) {
memset (&wvctx, 0, sizeof (wvctx));
- wvctx.ctx = WavpackOpenFileInput (it->fname, NULL, OPEN_2CH_MAX|OPEN_WVC, 0);
+
+ wvctx.file = deadbeef->fopen (it->fname);
+ if (!wvctx.file) {
+ return -1;
+ }
+ wvctx.ctx = WavpackOpenFileInputEx (&wsr, wvctx.file, NULL, NULL, OPEN_2CH_MAX/*|OPEN_WVC*/, 0);
if (!wvctx.ctx) {
+ plugin.free ();
return -1;
}
plugin.info.bps = WavpackGetBitsPerSample (wvctx.ctx);
@@ -66,8 +125,13 @@ wv_init (DB_playItem_t *it) {
static void
wv_free (void) {
+ if (wvctx.file) {
+ deadbeef->fclose (wvctx.file);
+ wvctx.file = NULL;
+ }
if (wvctx.ctx) {
WavpackCloseFile (wvctx.ctx);
+ wvctx.ctx = NULL;
}
memset (&wvctx, 0, sizeof (wvctx));
}
@@ -141,9 +205,15 @@ wv_seek (float sec) {
static DB_playItem_t *
wv_insert (DB_playItem_t *after, const char *fname) {
- WavpackContext *ctx = WavpackOpenFileInput (fname, NULL, 0, 0);
+
+ DB_FILE *fp = deadbeef->fopen (fname);
+ if (!fp) {
+ return NULL;
+ }
+ WavpackContext *ctx = WavpackOpenFileInputEx (&wsr, fp, NULL, NULL, 0, 0);
if (!ctx) {
trace ("WavpackOpenFileInput failed");
+ deadbeef->fclose (fp);
return NULL;
}
int totalsamples = WavpackGetNumSamples (ctx);
@@ -152,6 +222,7 @@ wv_insert (DB_playItem_t *after, const char *fname) {
float duration = (float)totalsamples / samplerate;
DB_playItem_t *cue_after = deadbeef->pl_insert_cue (after, fname, &plugin, "wv", totalsamples, samplerate);
if (cue_after) {
+ deadbeef->fclose (fp);
return cue_after;
}
@@ -163,18 +234,15 @@ wv_insert (DB_playItem_t *after, const char *fname) {
trace ("wv: totalsamples=%d, samplerate=%d, duration=%f\n", totalsamples, samplerate, duration);
- FILE *fp = fopen (fname, "rb");
- if (fp) {
- int apeerr = deadbeef->junk_read_ape (it, fp);
- if (!apeerr) {
- trace ("wv: ape tag found\n");
- }
- int v1err = deadbeef->junk_read_id3v1 (it, fp);
- if (!v1err) {
- trace ("wv: id3v1 tag found\n");
- }
- fclose (fp);
+ int apeerr = deadbeef->junk_read_ape (it, fp);
+ if (!apeerr) {
+ trace ("wv: ape tag found\n");
+ }
+ int v1err = deadbeef->junk_read_id3v1 (it, fp);
+ if (!v1err) {
+ trace ("wv: id3v1 tag found\n");
}
+ deadbeef->fclose (fp);
deadbeef->pl_add_meta (it, "title", NULL);
after = deadbeef->pl_insert_item (after, it);