aboutsummaryrefslogtreecommitdiffstats
path: root/src/decoder
diff options
context:
space:
mode:
authorMax Kellermann <max@duempel.org>2009-01-17 11:43:13 +0100
committerMax Kellermann <max@duempel.org>2009-01-17 11:46:31 +0100
commitd83eff80a51d7111f3df28dcc65fab9ebdf61632 (patch)
tree050b9a02f7b3a8cdf299e05faafcfd80261d3759 /src/decoder
parentda6f8c270a6f8affddc4ad9fd239cf20fa8c12a4 (diff)
downloadmpd-d83eff80a51d7111f3df28dcc65fab9ebdf61632.tar.gz
mpd-d83eff80a51d7111f3df28dcc65fab9ebdf61632.tar.xz
mpd-d83eff80a51d7111f3df28dcc65fab9ebdf61632.zip
oggvorbis: disable seeking on remote songs
When libvorbis knows that a song is seekable, it seeks around like crazy in the file before starting to decode it. This is very expensive on remote HTTP resources, and delays MPD for 10 or 20 seconds. This patch disables seeking on remote songs, because the advantages of quickly playing a song seem to weigh more than the theoretical ability of seeking for most MPD users. If users feel this feature is needed, we will make a configuration option for that.
Diffstat (limited to '')
-rw-r--r--src/decoder/oggvorbis_plugin.c32
1 files changed, 27 insertions, 5 deletions
diff --git a/src/decoder/oggvorbis_plugin.c b/src/decoder/oggvorbis_plugin.c
index 63722bdd8..e935870de 100644
--- a/src/decoder/oggvorbis_plugin.c
+++ b/src/decoder/oggvorbis_plugin.c
@@ -20,6 +20,7 @@
#include "_ogg_common.h"
#include "config.h"
+#include "ls.h"
#ifndef HAVE_TREMOR
#include <vorbis/vorbisfile.h>
@@ -51,7 +52,9 @@
typedef struct _OggCallbackData {
struct decoder *decoder;
+
struct input_stream *input_stream;
+ bool seekable;
} OggCallbackData;
static size_t ogg_read_cb(void *ptr, size_t size, size_t nmemb, void *vdata)
@@ -69,9 +72,11 @@ static size_t ogg_read_cb(void *ptr, size_t size, size_t nmemb, void *vdata)
static int ogg_seek_cb(void *vdata, ogg_int64_t offset, int whence)
{
const OggCallbackData *data = (const OggCallbackData *) vdata;
- if(decoder_get_command(data->decoder) == DECODE_COMMAND_STOP)
- return -1;
- return input_stream_seek(data->input_stream, offset, whence) ? 0 : -1;
+
+ return data->seekable &&
+ decoder_get_command(data->decoder) != DECODE_COMMAND_STOP &&
+ input_stream_seek(data->input_stream, offset, whence)
+ ? 0 : -1;
}
/* TODO: check Ogg libraries API and see if we can just not have this func */
@@ -209,6 +214,22 @@ vorbis_send_comments(struct decoder *decoder, struct input_stream *is,
tag_free(tag);
}
+static bool
+oggvorbis_seekable(struct decoder *decoder)
+{
+ char *uri;
+ bool seekable;
+
+ uri = decoder_get_uri(decoder);
+ /* disable seeking on remote streams, because libvorbis seeks
+ around like crazy, and due to being very expensive, this
+ delays song playback my 10 or 20 seconds */
+ seekable = !uri_has_scheme(uri);
+ g_free(uri);
+
+ return seekable;
+}
+
/* public */
static void
vorbis_stream_decode(struct decoder *decoder,
@@ -237,8 +258,9 @@ vorbis_stream_decode(struct decoder *decoder,
moved it */
input_stream_seek(input_stream, 0, SEEK_SET);
- data.input_stream = input_stream;
data.decoder = decoder;
+ data.input_stream = input_stream;
+ data.seekable = input_stream->seekable && oggvorbis_seekable(decoder);
callbacks.read_func = ogg_read_cb;
callbacks.seek_func = ogg_seek_cb;
@@ -314,7 +336,7 @@ vorbis_stream_decode(struct decoder *decoder,
if (total_time < 0)
total_time = 0;
decoder_initialized(decoder, &audio_format,
- input_stream->seekable,
+ data.seekable,
total_time);
initialized = true;
}