From 33783306bf5a108fd85604654ec52a99f8c3f16a Mon Sep 17 00:00:00 2001 From: Alexey Yakovenko Date: Sun, 4 Oct 2009 22:32:42 +0200 Subject: added streaming over ftp support including seeking added special-case for fseek+ftell when calculating file length --- plugins/vfs_curl/vfs_curl.c | 20 +++++++++++++------- plugins/vorbis/vorbis.c | 23 ++++++++++++----------- 2 files changed, 25 insertions(+), 18 deletions(-) diff --git a/plugins/vfs_curl/vfs_curl.c b/plugins/vfs_curl/vfs_curl.c index ace14713..e1105b1d 100644 --- a/plugins/vfs_curl/vfs_curl.c +++ b/plugins/vfs_curl/vfs_curl.c @@ -46,6 +46,7 @@ typedef struct { char *url; uint8_t buffer[BUFFER_SIZE]; int64_t pos; // position in stream; use "& BUFFER_MASK" to make it index into ringbuffer + int seektoend; // indicates that next tell must return length int64_t length; int32_t remaining; // remaining bytes in buffer read from stream int32_t skipbytes; @@ -118,10 +119,6 @@ http_size_request_handler (void *ptr, size_t size, size_t nmemb, void *stream) { fp->length = atoi (cl); trace ("vfs_curl: file size is %d bytes\n", fp->length); } -// else { -// trace ("vfs_curl: unable to get file size\n"); -// fp->length = -1; // infinite -// } return size * nmemb; } @@ -229,6 +226,7 @@ http_read (void *ptr, size_t size, size_t nmemb, DB_FILE *stream) { assert (stream); assert (ptr); HTTP_FILE *fp = (HTTP_FILE *)stream; + fp->seektoend = 0; int sz = size * nmemb; // assert (size * nmemb <= BUFFER_SIZE); // trace ("readpos=%d, readsize=%d\n", fp->pos & BUFFER_SIZE, sz); @@ -281,12 +279,17 @@ http_read (void *ptr, size_t size, size_t nmemb, DB_FILE *stream) { static int http_seek (DB_FILE *stream, int64_t offset, int whence) { trace ("http_seek %x %d\n", offset, whence); + assert (stream); + HTTP_FILE *fp = (HTTP_FILE *)stream; + fp->seektoend = 0; if (whence == SEEK_END) { + if (offset == 0) { + fp->seektoend = 1; + return 0; + } trace ("vfs_curl: can't seek in curl stream relative to EOF\n"); return -1; } - assert (stream); - HTTP_FILE *fp = (HTTP_FILE *)stream; if (!fp->tid) { if (offset == 0 && (whence == SEEK_SET || whence == SEEK_CUR)) { return 0; @@ -334,6 +337,9 @@ static int64_t http_tell (DB_FILE *stream) { assert (stream); HTTP_FILE *fp = (HTTP_FILE *)stream; + if (fp->seektoend) { + return fp->length; + } return fp->pos + fp->skipbytes; } @@ -366,7 +372,7 @@ http_getlength (DB_FILE *stream) { return fp->length; } -static const char *scheme_names[] = { "http://", NULL }; +static const char *scheme_names[] = { "http://", "ftp://", NULL }; // standard stdio vfs static DB_vfs_t plugin = { diff --git a/plugins/vorbis/vorbis.c b/plugins/vorbis/vorbis.c index 48b6c4c4..78496458 100644 --- a/plugins/vorbis/vorbis.c +++ b/plugins/vorbis/vorbis.c @@ -27,7 +27,7 @@ #define min(x,y) ((x)<(y)?(x):(y)) #define max(x,y) ((x)>(y)?(x):(y)) -//#define trace(...) { fprintf(stderr, __VA_ARGS__); } +//#define trace(...) { fprintf (stderr, __VA_ARGS__); } #define trace(fmt,...) static DB_decoder_t plugin; @@ -54,9 +54,6 @@ cvorbis_fread (void *ptr, size_t size, size_t nmemb, void *datasource) { static int cvorbis_fseek (void *datasource, ogg_int64_t offset, int whence) { DB_FILE *f = (DB_FILE *)datasource; - if (f->vfs->streaming) { - return -1; - } return deadbeef->fseek (datasource, offset, whence); } @@ -119,7 +116,8 @@ cvorbis_init (DB_playItem_t *it) { } memset (&plugin.info, 0, sizeof (plugin.info)); - if (file->vfs->streaming) { + int ln = deadbeef->fgetlength (file); + if (file->vfs->streaming && ln == -1) { ov_callbacks ovcb = { .read_func = cvorbis_fread, .seek_func = NULL, @@ -134,6 +132,7 @@ cvorbis_init (DB_playItem_t *it) { plugin.free (); return -1; } + it->duration = -1; } else { @@ -151,6 +150,7 @@ cvorbis_init (DB_playItem_t *it) { plugin.free (); return -1; } + it->duration = ov_time_total (&vorbis_file, -1); } vi = ov_info (&vorbis_file, -1); if (!vi) { // not a vorbis stream @@ -177,11 +177,12 @@ cvorbis_init (DB_playItem_t *it) { } else { startsample = 0; - endsample = ov_pcm_total (&vorbis_file, -1)-1; - if (endsample <= 0) { + if (it->duration < 0) { endsample = -1; } - it->duration = -1; + else { + endsample = ov_pcm_total (&vorbis_file, -1)-1; + } vorbis_comment *vc = ov_comment (&vorbis_file, -1); update_vorbis_comments (it, vc); } @@ -285,7 +286,7 @@ cvorbis_seek_sample (int sample) { return -1; int tell = ov_pcm_tell (&vorbis_file); if (tell != sample) { - fprintf (stderr, "oggvorbis: failed to do sample-accurate seek (%d->%d)\n", sample, tell); + trace ("oggvorbis: failed to do sample-accurate seek (%d->%d)\n", sample, tell); } currentsample = sample; plugin.info.readpos = (float)(ov_pcm_tell(&vorbis_file) - startsample)/vi->rate; @@ -302,7 +303,7 @@ cvorbis_insert (DB_playItem_t *after, const char *fname) { // check for validity DB_FILE *fp = deadbeef->fopen (fname); if (!fp) { - fprintf (stderr, "vorbis: failed to fopen %s\n", fname); + trace ("vorbis: failed to fopen %s\n", fname); return NULL; } if (fp->vfs->streaming) { @@ -326,7 +327,7 @@ cvorbis_insert (DB_playItem_t *after, const char *fname) { 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); + trace ("vorbis: failed to ov_open %s\n", fname); return NULL; } float duration = ov_time_total (&vorbis_file, -1); -- cgit v1.2.3