diff options
author | Alexey Yakovenko <wakeroid@gmail.com> | 2009-09-28 22:56:57 +0200 |
---|---|---|
committer | Alexey Yakovenko <wakeroid@gmail.com> | 2009-09-28 22:56:57 +0200 |
commit | b5bedb49dad2da3aab4a997ac6daad1c4f30d67a (patch) | |
tree | 82390feb2bc4925b707f11f65e08f7523e9dad90 /plugins | |
parent | 75d630d07d325ca8ac895dc23186819c00003926 (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.c | 53 | ||||
-rw-r--r-- | plugins/flac/flac.c | 160 | ||||
-rw-r--r-- | plugins/mpgmad/mpgmad.c | 102 | ||||
-rw-r--r-- | plugins/vorbis/vorbis.c | 48 | ||||
-rw-r--r-- | plugins/wavpack/wavpack.c | 94 |
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); |