decoder_thread: don't try a plugin twice (MIME type & suffix)

Manage a linked list of plugins which were already tried.
This commit is contained in:
Max Kellermann 2010-01-17 16:47:04 +01:00
parent 006f4be71c
commit 8ac776c58b
2 changed files with 57 additions and 10 deletions

1
NEWS
View File

@ -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

View File

@ -156,45 +156,86 @@ decoder_file_decode(const struct decoder_plugin *plugin,
return decoder->dc->state != DECODE_STATE_START;
}
/**
* 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);