aboutsummaryrefslogtreecommitdiffstats
path: root/src/decoder_thread.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/decoder_thread.c')
-rw-r--r--src/decoder_thread.c66
1 files changed, 56 insertions, 10 deletions
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);