summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--deadbeef.h3
-rw-r--r--main.c9
-rw-r--r--plugins.c1
-rw-r--r--plugins/mpgmad/mpgmad.c3
-rw-r--r--plugins/vfs_curl/vfs_curl.c24
-rw-r--r--plugins/vorbis/vorbis.c3
-rw-r--r--session.c1
-rw-r--r--streamer.c28
-rw-r--r--vfs.c7
-rw-r--r--vfs.h1
10 files changed, 74 insertions, 6 deletions
diff --git a/deadbeef.h b/deadbeef.h
index 20fccd5d..b97de2e8 100644
--- a/deadbeef.h
+++ b/deadbeef.h
@@ -240,6 +240,7 @@ typedef struct {
const char *(*fget_content_type) (DB_FILE *stream);
const char *(*fget_content_name) (DB_FILE *stream);
const char *(*fget_content_genre) (DB_FILE *stream);
+ void (*fstop) (DB_FILE *stream);
// message passing
int (*sendmessage) (uint32_t id, uintptr_t ctx, uint32_t p1, uint32_t p2);
// configuration access
@@ -293,6 +294,7 @@ typedef struct DB_plugin_s {
} DB_plugin_t;
typedef struct {
+ DB_FILE *file;
int bps;
int channels;
int samplerate;
@@ -396,6 +398,7 @@ typedef struct DB_vfs_s {
int64_t (*tell) (DB_FILE *stream);
void (*rewind) (DB_FILE *stream);
int64_t (*getlength)(DB_FILE *stream);
+ void (*stop)(DB_FILE *stream);
const char * (*get_content_type) (DB_FILE *stream);
const char * (*get_content_name) (DB_FILE *stream);
const char * (*get_content_genre) (DB_FILE *stream);
diff --git a/main.c b/main.c
index a97475a8..a09da293 100644
--- a/main.c
+++ b/main.c
@@ -733,18 +733,21 @@ main (int argc, char *argv[]) {
gtk_widget_show (mainwin);
gtk_main ();
+ // save config
+ pl_save (defpl);
+ conf_save ();
+ // stop receiving messages from outside
+ server_close ();
+ // at this point we can simply do exit(0), but let's clean up for debugging
gtkpl_free (&main_playlist);
gtkpl_free (&search_playlist);
- server_close ();
gdk_threads_leave ();
messagepump_free ();
p_free ();
streamer_free ();
codec_free_locking ();
session_save (sessfile);
- pl_save (defpl);
pl_free ();
- conf_save ();
conf_free ();
plug_unload_all ();
return 0;
diff --git a/plugins.c b/plugins.c
index 3ed508e5..4fe09eaa 100644
--- a/plugins.c
+++ b/plugins.c
@@ -113,6 +113,7 @@ static DB_functions_t deadbeef_api = {
.fget_content_type = vfs_get_content_type,
.fget_content_name = vfs_get_content_name,
.fget_content_genre = vfs_get_content_genre,
+ .fstop = vfs_fstop,
// message passing
.sendmessage = messagepump_push,
// configuration access
diff --git a/plugins/mpgmad/mpgmad.c b/plugins/mpgmad/mpgmad.c
index 8e54b6c8..763b7fb1 100644
--- a/plugins/mpgmad/mpgmad.c
+++ b/plugins/mpgmad/mpgmad.c
@@ -470,7 +470,7 @@ cmp3_scan_stream (buffer_t *buffer, int sample) {
static int
cmp3_init (DB_playItem_t *it) {
memset (&buffer, 0, sizeof (buffer));
- buffer.file = deadbeef->fopen (it->fname);
+ buffer.file = plugin.info.file = deadbeef->fopen (it->fname);
if (!buffer.file) {
return -1;
}
@@ -783,6 +783,7 @@ cmp3_decode_float32 (void) {
static void
cmp3_free (void) {
+ plugin.info.file = NULL;
if (buffer.file) {
deadbeef->fclose (buffer.file);
buffer.file = NULL;
diff --git a/plugins/vfs_curl/vfs_curl.c b/plugins/vfs_curl/vfs_curl.c
index 3619ab6e..42211fe3 100644
--- a/plugins/vfs_curl/vfs_curl.c
+++ b/plugins/vfs_curl/vfs_curl.c
@@ -290,6 +290,7 @@ http_curl_write_abort (void *ptr, size_t size, size_t nmemb, void *stream) {
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;
if (fp->status == STATUS_ABORTED) {
@@ -342,6 +343,8 @@ http_thread_func (uintptr_t ctx) {
curl_easy_setopt (curl, CURLOPT_HEADERFUNCTION, http_content_header_handler);
curl_easy_setopt (curl, CURLOPT_HEADERDATA, ctx);
curl_easy_setopt (curl, CURLOPT_PROGRESSFUNCTION, http_curl_control);
+ curl_easy_setopt (curl, CURLOPT_NOPROGRESS, 0);
+ curl_easy_setopt (curl, CURLOPT_PROGRESSDATA, ctx);
// enable up to 10 redirects
curl_easy_setopt (curl, CURLOPT_FOLLOWLOCATION, 1);
curl_easy_setopt (curl, CURLOPT_MAXREDIRS, 10);
@@ -589,6 +592,9 @@ http_getlength (DB_FILE *stream) {
trace ("http_getlength\n");
assert (stream);
HTTP_FILE *fp = (HTTP_FILE *)stream;
+ if (fp->status == STATUS_ABORTED) {
+ return -1;
+ }
if (!fp->tid) {
http_start_streamer (fp);
}
@@ -604,6 +610,9 @@ http_get_content_type (DB_FILE *stream) {
trace ("http_get_content_type\n");
assert (stream);
HTTP_FILE *fp = (HTTP_FILE *)stream;
+ if (fp->status == STATUS_ABORTED) {
+ return NULL;
+ }
if (fp->gotheader) {
return fp->content_type;
}
@@ -622,6 +631,9 @@ http_get_content_name (DB_FILE *stream) {
trace ("http_get_content_name\n");
assert (stream);
HTTP_FILE *fp = (HTTP_FILE *)stream;
+ if (fp->status == STATUS_ABORTED) {
+ return NULL;
+ }
if (fp->gotheader) {
return fp->content_name;
}
@@ -640,6 +652,9 @@ http_get_content_genre (DB_FILE *stream) {
trace ("http_get_content_genre\n");
assert (stream);
HTTP_FILE *fp = (HTTP_FILE *)stream;
+ if (fp->status == STATUS_ABORTED) {
+ return NULL;
+ }
if (fp->gotheader) {
return fp->content_genre;
}
@@ -653,6 +668,14 @@ http_get_content_genre (DB_FILE *stream) {
return fp->content_genre;
}
+static void
+http_stop (DB_FILE *stream) {
+ trace ("http_stop\n");
+ assert (stream);
+ HTTP_FILE *fp = (HTTP_FILE *)stream;
+ fp->status = STATUS_ABORTED;
+}
+
static const char *scheme_names[] = { "http://", "ftp://", NULL };
// standard stdio vfs
@@ -676,6 +699,7 @@ static DB_vfs_t plugin = {
.get_content_type = http_get_content_type,
.get_content_name = http_get_content_name,
.get_content_genre = http_get_content_type,
+ .stop = http_stop,
.scheme_names = scheme_names,
.streaming = 1
};
diff --git a/plugins/vorbis/vorbis.c b/plugins/vorbis/vorbis.c
index 8a32bd86..31e252eb 100644
--- a/plugins/vorbis/vorbis.c
+++ b/plugins/vorbis/vorbis.c
@@ -110,7 +110,7 @@ cvorbis_init (DB_playItem_t *it) {
cur_bit_stream = -1;
ptrack = it;
- file = deadbeef->fopen (it->fname);
+ file = plugin.info.file = deadbeef->fopen (it->fname);
if (!file) {
return -1;
}
@@ -191,6 +191,7 @@ cvorbis_init (DB_playItem_t *it) {
static void
cvorbis_free (void) {
+ plugin.info.file = NULL;
if (file) {
ptrack = NULL;
ov_clear (&vorbis_file);
diff --git a/session.c b/session.c
index a757c469..d99e3c4a 100644
--- a/session.c
+++ b/session.c
@@ -19,6 +19,7 @@
#include <stdio.h>
#include <string.h>
#include <stdint.h>
+#include <unistd.h>
#include "session.h"
#include "common.h"
#include "deadbeef.h"
diff --git a/streamer.c b/streamer.c
index 2d7cd377..97d5154e 100644
--- a/streamer.c
+++ b/streamer.c
@@ -57,6 +57,7 @@ static float g_fbuffer[INPUT_BUFFER_SIZE];
#define SRC_BUFFER_SIZE (INPUT_BUFFER_SIZE*2)
static float g_srcbuffer[SRC_BUFFER_SIZE];
static int streaming_terminate;
+static playItem_t *streamer_initializing_item;
// buffer up to 3 seconds at 44100Hz stereo
#define STREAM_BUFFER_SIZE 0x80000 // slightly more than 3 seconds of 44100 stereo
@@ -88,10 +89,14 @@ static playItem_t *orig_streaming_song;
static int streamer_buffering;
+// to allow interruption of stall file requests
+static DB_FILE *streamer_file;
+
playItem_t *
streamer_get_streaming_track (void) {
return orig_streaming_song;
}
+
// playlist must call that whenever item was removed
void
streamer_song_removed_notify (playItem_t *it) {
@@ -133,7 +138,7 @@ streamer_set_current (playItem_t *it) {
}
if (!it->decoder && it->filetype && !strcmp (it->filetype, "content")) {
// try to get content-type
- DB_FILE *fp = vfs_fopen (it->fname);
+ DB_FILE *fp = streamer_file = vfs_fopen (it->fname);
const char *ext = NULL;
if (fp) {
const char *ct = vfs_get_content_type (fp);
@@ -146,6 +151,7 @@ streamer_set_current (playItem_t *it) {
ext = "ogg";
}
}
+ streamer_file = NULL;
vfs_fclose (fp);
}
if (ext) {
@@ -165,7 +171,13 @@ streamer_set_current (playItem_t *it) {
}
}
if (it->decoder) {
+ streamer_lock ();
+ streamer_initializing_item = it;
+ streamer_unlock ();
int ret = it->decoder->init (DB_PLAYITEM (it));
+ streamer_lock ();
+ streamer_initializing_item = NULL;
+ streamer_unlock ();
pl_item_copy (&str_streaming_song, it);
if (ret < 0) {
trace ("decoder->init returned %d\n", ret);
@@ -218,6 +230,20 @@ streamer_set_nextsong (int song, int pstate) {
// no sense to wait until end of previous song, reset buffer
bytes_until_next_song = 0;
playpos = 0;
+ // try to interrupt file operation
+ streamer_lock ();
+ if (streamer_file && streamer_file->vfs->streaming) {
+ trace ("interrupting streamer file access...\n");
+ vfs_fstop (streamer_file);
+ }
+ else if (streamer_initializing_item) {
+ playItem_t *it = streamer_initializing_item;
+ if (it->decoder->info.file && it->decoder->info.file->vfs->streaming) {
+ trace ("interrupting plugin stream %p...\n", it->decoder->info.file);
+ vfs_fstop (it->decoder->info.file);
+ }
+ }
+ streamer_unlock ();
}
}
diff --git a/vfs.c b/vfs.c
index 2c038fac..23b1628d 100644
--- a/vfs.c
+++ b/vfs.c
@@ -99,3 +99,10 @@ vfs_get_content_genre (DB_FILE *stream) {
}
return NULL;
}
+
+void
+vfs_fstop (DB_FILE *stream) {
+ if (stream->vfs->stop) {
+ stream->vfs->stop (stream);
+ }
+}
diff --git a/vfs.h b/vfs.h
index 599e63e4..65610cf2 100644
--- a/vfs.h
+++ b/vfs.h
@@ -32,5 +32,6 @@ int64_t vfs_fgetlength (DB_FILE *stream);
const char *vfs_get_content_type (DB_FILE *stream);
const char *vfs_get_content_name (DB_FILE *stream);
const char *vfs_get_content_genre (DB_FILE *stream);
+void vfs_fstop (DB_FILE *stream);
#endif // __VFS_H