aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMax Kellermann <max@duempel.org>2010-01-17 16:47:04 +0100
committerMax Kellermann <max@duempel.org>2010-01-17 16:47:04 +0100
commit8ac776c58b69a94fce793d16e477a88207ce0d27 (patch)
tree18b10c9a513b38e96224e3300ebbad55072ba93d
parent006f4be71c0a77a7bc166e9abe22dbfada9c25a6 (diff)
downloadmpd-8ac776c58b69a94fce793d16e477a88207ce0d27.tar.gz
mpd-8ac776c58b69a94fce793d16e477a88207ce0d27.tar.xz
mpd-8ac776c58b69a94fce793d16e477a88207ce0d27.zip
decoder_thread: don't try a plugin twice (MIME type & suffix)
Manage a linked list of plugins which were already tried.
-rw-r--r--NEWS1
-rw-r--r--src/decoder_thread.c66
2 files changed, 57 insertions, 10 deletions
diff --git a/NEWS b/NEWS
index 0702c9436..7cc085e57 100644
--- a/NEWS
+++ b/NEWS
@@ -19,6 +19,7 @@ ver 0.16 (20??/??/??)
- added tags "ArtistSort", "AlbumArtistSort"
- id3: revised "performer" tag support
* decoders:
+ - don't try a plugin twice (MIME type & suffix)
- ffmpeg: support multiple tags
- ffmpeg: convert metadata to generic format
- sndfile: new decoder plugin based on libsndfile
diff --git a/src/decoder_thread.c b/src/decoder_thread.c
index 1539117f4..631a7a0e3 100644
--- a/src/decoder_thread.c
+++ b/src/decoder_thread.c
@@ -157,44 +157,85 @@ decoder_file_decode(const struct decoder_plugin *plugin,
}
/**
+ * Hack to allow tracking const decoder plugins in a GSList.
+ */
+static inline gpointer
+deconst_plugin(const struct decoder_plugin *plugin)
+{
+ union {
+ const struct decoder_plugin *in;
+ gpointer out;
+ } u = { .in = plugin };
+
+ return u.out;
+}
+
+/**
* Try decoding a stream, using plugins matching the stream's MIME type.
+ *
+ * @param tried_r a list of plugins which were tried
*/
static bool
-decoder_run_stream_mime_type(struct decoder *decoder, struct input_stream *is)
+decoder_run_stream_mime_type(struct decoder *decoder, struct input_stream *is,
+ GSList **tried_r)
{
+ assert(tried_r != NULL);
+
const struct decoder_plugin *plugin;
unsigned int next = 0;
if (is->mime == NULL)
return false;
- while ((plugin = decoder_plugin_from_mime_type(is->mime, next++)))
- if (plugin->stream_decode != NULL &&
- decoder_stream_decode(plugin, decoder, is))
+ while ((plugin = decoder_plugin_from_mime_type(is->mime, next++))) {
+ if (plugin->stream_decode == NULL)
+ continue;
+
+ if (g_slist_find(*tried_r, plugin) != NULL)
+ /* don't try a plugin twice */
+ continue;
+
+ if (decoder_stream_decode(plugin, decoder, is))
return true;
+ *tried_r = g_slist_prepend(*tried_r, deconst_plugin(plugin));
+ }
+
return false;
}
/**
* Try decoding a stream, using plugins matching the stream's URI
* suffix.
+ *
+ * @param tried_r a list of plugins which were tried
*/
static bool
decoder_run_stream_suffix(struct decoder *decoder, struct input_stream *is,
- const char *uri)
+ const char *uri, GSList **tried_r)
{
+ assert(tried_r != NULL);
+
const char *suffix = uri_get_suffix(uri);
const struct decoder_plugin *plugin = NULL;
if (suffix == NULL)
return false;
- while ((plugin = decoder_plugin_from_suffix(suffix, plugin)) != NULL)
- if (plugin->stream_decode != NULL &&
- decoder_stream_decode(plugin, decoder, is))
+ while ((plugin = decoder_plugin_from_suffix(suffix, plugin)) != NULL) {
+ if (plugin->stream_decode == NULL)
+ continue;
+
+ if (g_slist_find(*tried_r, plugin) != NULL)
+ /* don't try a plugin twice */
+ continue;
+
+ if (decoder_stream_decode(plugin, decoder, is))
return true;
+ *tried_r = g_slist_prepend(*tried_r, deconst_plugin(plugin));
+ }
+
return false;
}
@@ -231,15 +272,20 @@ decoder_run_stream(struct decoder *decoder, const char *uri)
decoder_lock(dc);
+ GSList *tried = NULL;
+
success = dc->command == DECODE_COMMAND_STOP ||
/* first we try mime types: */
- decoder_run_stream_mime_type(decoder, input_stream) ||
+ decoder_run_stream_mime_type(decoder, input_stream, &tried) ||
/* if that fails, try suffix matching the URL: */
- decoder_run_stream_suffix(decoder, input_stream, uri) ||
+ decoder_run_stream_suffix(decoder, input_stream, uri,
+ &tried) ||
/* fallback to mp3: this is needed for bastard streams
that don't have a suffix or set the mimeType */
decoder_run_stream_fallback(decoder, input_stream);
+ g_slist_free(tried);
+
decoder_unlock(dc);
input_stream_close(input_stream);
decoder_lock(dc);