diff options
Diffstat (limited to 'plugins/vfs_curl/vfs_curl.c')
-rw-r--r-- | plugins/vfs_curl/vfs_curl.c | 96 |
1 files changed, 44 insertions, 52 deletions
diff --git a/plugins/vfs_curl/vfs_curl.c b/plugins/vfs_curl/vfs_curl.c index 3185df67..1ef633b1 100644 --- a/plugins/vfs_curl/vfs_curl.c +++ b/plugins/vfs_curl/vfs_curl.c @@ -24,8 +24,8 @@ #include <curl/curlver.h> #include "../../deadbeef.h" -//#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)) @@ -70,6 +70,9 @@ static DB_vfs_t plugin; static char http_err[CURL_ERROR_SIZE]; +static int vfs_curl_abort; +static int vfs_curl_count; + static size_t http_content_header_handler (void *ptr, size_t size, size_t nmemb, void *stream); @@ -190,26 +193,6 @@ http_curl_write (void *ptr, size_t size, size_t nmemb, void *stream) { return nmemb * size - avail; } -#if 0 -static size_t -http_size_header_handler (void *ptr, size_t size, size_t nmemb, void *stream) { - assert (stream); - HTTP_FILE *fp = (HTTP_FILE *)stream; - // don't copy/allocate mem, just grep for "Content-Length: " - const char *cl = strcasestr (ptr, "Content-Length:"); - if (cl) { - cl += 15; - while (*cl <= 0x20) { - cl++; - } - fp->length = atoi (cl); - trace ("vfs_curl: file size is %d bytes\n", fp->length); - return 0; - } - return size * nmemb; -} -#endif - static const uint8_t * parse_header (const uint8_t *p, const uint8_t *e, uint8_t *key, int keysize, uint8_t *value, int valuesize) { int sz; // will hold lenght of extracted string @@ -313,25 +296,25 @@ http_content_header_handler (void *ptr, size_t size, size_t nmemb, void *stream) return size * nmemb; } -//static size_t -//http_curl_write_abort (void *ptr, size_t size, size_t nmemb, void *stream) { -// return 0; -//} - static int http_curl_control (void *stream, double dltotal, double dlnow, double ultotal, double ulnow) { -// trace ("http_curl_control\n"); - assert (stream); HTTP_FILE *fp = (HTTP_FILE *)stream; + trace ("http_curl_control, status = %d\n", fp ? fp->status : -1); + assert (stream); if (fp->status == STATUS_ABORTED) { trace ("vfs_curl STATUS_ABORTED in progress callback\n"); return -1; } + if (vfs_curl_abort) { + trace ("vfs_curl: aborting stream %p due to external request\n"); + return -1; + } return 0; } static void http_thread_func (void *ctx) { + vfs_curl_count++; HTTP_FILE *fp = (HTTP_FILE *)ctx; CURL *curl; curl = curl_easy_init (); @@ -339,26 +322,6 @@ http_thread_func (void *ctx) { fp->status = STATUS_INITIAL; int status; -#if 0 - // get filesize (once) - curl_easy_setopt (curl, CURLOPT_URL, fp->url); - curl_easy_setopt (curl, CURLOPT_NOBODY, 0); - curl_easy_setopt (curl, CURLOPT_FOLLOWLOCATION, 1); - curl_easy_setopt (curl, CURLOPT_MAXREDIRS, 10); - curl_easy_setopt (curl, CURLOPT_HEADERFUNCTION, http_size_header_handler); - curl_easy_setopt (curl, CURLOPT_HEADERDATA, ctx); - curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, http_curl_write_abort); - curl_easy_setopt (curl, CURLOPT_PROGRESSFUNCTION, http_curl_control); - curl_easy_setopt (curl, CURLOPT_FOLLOWLOCATION, 1); - curl_easy_setopt (curl, CURLOPT_MAXREDIRS, 10); - status = curl_easy_perform(curl); -#if 0 - if (status != 0) { - trace ("vfs_curl: curl_easy_perform failed while getting filesize, status %d\n", status); - } -#endif -#endif -// fp->status = STATUS_STARTING; trace ("vfs_curl: started loading data\n"); for (;;) { @@ -436,6 +399,7 @@ http_thread_func (void *ctx) { fp->status = STATUS_FINISHED; deadbeef->mutex_unlock (fp->mutex); fp->tid = 0; + vfs_curl_count--; } static void @@ -497,7 +461,7 @@ http_read (void *ptr, size_t size, size_t nmemb, DB_FILE *stream) { while (fp->status != STATUS_FINISHED && sz > 0) { // wait until data is available - while ((fp->remaining == 0 || fp->skipbytes > 0) && fp->status != STATUS_FINISHED) { + while ((fp->remaining == 0 || fp->skipbytes > 0) && fp->status != STATUS_FINISHED && !vfs_curl_abort) { deadbeef->mutex_lock (fp->mutex); int skip = min (fp->remaining, fp->skipbytes); if (skip > 0) { @@ -651,7 +615,7 @@ http_get_content_type (DB_FILE *stream) { http_start_streamer (fp); } trace ("http_get_content_type waiting for response...\n"); - while (fp->status != STATUS_FINISHED && fp->status != STATUS_ABORTED && !fp->gotheader) { + while (fp->status != STATUS_FINISHED && fp->status != STATUS_ABORTED && !fp->gotheader && !vfs_curl_abort) { usleep (3000); } return fp->content_type; @@ -672,7 +636,7 @@ http_get_content_name (DB_FILE *stream) { http_start_streamer (fp); } trace ("http_get_content_name waiting for response...\n"); - while (fp->status != STATUS_FINISHED && fp->status != STATUS_ABORTED && !fp->gotheader) { + while (fp->status != STATUS_FINISHED && fp->status != STATUS_ABORTED && !fp->gotheader && !vfs_curl_abort) { usleep (3000); } return fp->content_name; @@ -709,6 +673,32 @@ http_stop (DB_FILE *stream) { fp->status = STATUS_ABORTED; } +static int +vfs_curl_on_abort (DB_event_t *ev, uintptr_t data) { + trace ("vfs_curl: got abort signal!\n"); + if (vfs_curl_count > 0) { + vfs_curl_abort = 1; + while (vfs_curl_count > 0) { + usleep (20000); + } + vfs_curl_abort = 0; + } + return 0; +} + +static int +vfs_curl_start (void) { + deadbeef->ev_subscribe (DB_PLUGIN (&plugin), DB_EV_ABORTREAD, DB_CALLBACK (vfs_curl_on_abort), 0); + return 0; +} + +static int +vfs_curl_stop (void) { + deadbeef->ev_unsubscribe (DB_PLUGIN (&plugin), DB_EV_ABORTREAD, DB_CALLBACK (vfs_curl_on_abort), 0); + vfs_curl_on_abort (NULL, 0); + return 0; +} + static const char *scheme_names[] = { "http://", "ftp://", NULL }; // standard stdio vfs @@ -722,6 +712,8 @@ static DB_vfs_t plugin = { .plugin.author = "Alexey Yakovenko", .plugin.email = "waker@users.sourceforge.net", .plugin.website = "http://deadbeef.sf.net", + .plugin.start = vfs_curl_start, + .plugin.stop = vfs_curl_stop, .open = http_open, .close = http_close, .read = http_read, |