aboutsummaryrefslogtreecommitdiffstats
path: root/src/DecoderThread.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'src/DecoderThread.cxx')
-rw-r--r--src/DecoderThread.cxx106
1 files changed, 42 insertions, 64 deletions
diff --git a/src/DecoderThread.cxx b/src/DecoderThread.cxx
index f70b7c34f..556ab327e 100644
--- a/src/DecoderThread.cxx
+++ b/src/DecoderThread.cxx
@@ -179,74 +179,58 @@ deconst_plugin(const struct DecoderPlugin *plugin)
return const_cast<struct DecoderPlugin *>(plugin);
}
-/**
- * Try decoding a stream, using plugins matching the stream's MIME type.
- *
- * @param tried_r a list of plugins which were tried
- */
+gcc_pure
static bool
-decoder_run_stream_mime_type(Decoder &decoder, struct input_stream *is,
- GSList **tried_r)
+decoder_check_plugin_mime(const DecoderPlugin &plugin, const input_stream &is)
{
- assert(tried_r != nullptr);
-
- const struct DecoderPlugin *plugin;
- unsigned int next = 0;
-
- if (is->mime.empty())
- return false;
-
- while ((plugin = decoder_plugin_from_mime_type(is->mime.c_str(),
- next++))) {
- if (plugin->stream_decode == nullptr)
- continue;
-
- if (g_slist_find(*tried_r, plugin) != nullptr)
- /* don't try a plugin twice */
- continue;
+ assert(plugin.stream_decode != nullptr);
- if (decoder_stream_decode(*plugin, decoder, is))
- return true;
+ return !is.mime.empty() && plugin.SupportsMimeType(is.mime.c_str());
+}
- *tried_r = g_slist_prepend(*tried_r, deconst_plugin(plugin));
- }
+gcc_pure
+static bool
+decoder_check_plugin_suffix(const DecoderPlugin &plugin, const char *suffix)
+{
+ assert(plugin.stream_decode != nullptr);
- return false;
+ return suffix != nullptr && plugin.SupportsSuffix(suffix);
}
-/**
- * Try decoding a stream, using plugins matching the stream's URI
- * suffix.
- *
- * @param tried_r a list of plugins which were tried
- */
+gcc_pure
static bool
-decoder_run_stream_suffix(Decoder &decoder, struct input_stream *is,
- const char *uri, GSList **tried_r)
+decoder_check_plugin(const DecoderPlugin &plugin, const input_stream &is,
+ const char *suffix)
{
- assert(tried_r != nullptr);
-
- const char *suffix = uri_get_suffix(uri);
- const struct DecoderPlugin *plugin = nullptr;
+ return plugin.stream_decode != nullptr &&
+ (decoder_check_plugin_mime(plugin, is) ||
+ decoder_check_plugin_suffix(plugin, suffix));
+}
- if (suffix == nullptr)
+static bool
+decoder_run_stream_plugin(Decoder &decoder, input_stream &is,
+ const char *suffix,
+ const DecoderPlugin &plugin,
+ bool &tried_r)
+{
+ if (!decoder_check_plugin(plugin, is, suffix))
return false;
- while ((plugin = decoder_plugin_from_suffix(suffix, plugin)) != nullptr) {
- if (plugin->stream_decode == nullptr)
- continue;
-
- if (g_slist_find(*tried_r, plugin) != nullptr)
- /* don't try a plugin twice */
- continue;
-
- if (decoder_stream_decode(*plugin, decoder, is))
- return true;
+ tried_r = true;
+ return decoder_stream_decode(plugin, decoder, &is);
+}
- *tried_r = g_slist_prepend(*tried_r, deconst_plugin(plugin));
- }
+static bool
+decoder_run_stream_locked(Decoder &decoder, input_stream &is,
+ const char *uri, bool &tried_r)
+{
+ const char *const suffix = uri_get_suffix(uri);
- return false;
+ using namespace std::placeholders;
+ const auto f = std::bind(decoder_run_stream_plugin,
+ std::ref(decoder), std::ref(is), suffix,
+ _1, std::ref(tried_r));
+ return decoder_plugins_try(f);
}
/**
@@ -282,21 +266,15 @@ decoder_run_stream(Decoder &decoder, const char *uri)
dc.Lock();
- GSList *tried = nullptr;
-
+ bool tried = false;
success = dc.command == DecoderCommand::STOP ||
- /* first we try mime types: */
- 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,
- &tried) ||
+ decoder_run_stream_locked(decoder, *input_stream, uri,
+ tried) ||
/* fallback to mp3: this is needed for bastard streams
that don't have a suffix or set the mimeType */
- (tried == nullptr &&
+ (!tried &&
decoder_run_stream_fallback(decoder, input_stream));
- g_slist_free(tried);
-
dc.Unlock();
input_stream->Close();
dc.Lock();