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:
parent
006f4be71c
commit
8ac776c58b
1
NEWS
1
NEWS
|
@ -19,6 +19,7 @@ ver 0.16 (20??/??/??)
|
||||||
- added tags "ArtistSort", "AlbumArtistSort"
|
- added tags "ArtistSort", "AlbumArtistSort"
|
||||||
- id3: revised "performer" tag support
|
- id3: revised "performer" tag support
|
||||||
* decoders:
|
* decoders:
|
||||||
|
- don't try a plugin twice (MIME type & suffix)
|
||||||
- ffmpeg: support multiple tags
|
- ffmpeg: support multiple tags
|
||||||
- ffmpeg: convert metadata to generic format
|
- ffmpeg: convert metadata to generic format
|
||||||
- sndfile: new decoder plugin based on libsndfile
|
- sndfile: new decoder plugin based on libsndfile
|
||||||
|
|
|
@ -156,45 +156,86 @@ decoder_file_decode(const struct decoder_plugin *plugin,
|
||||||
return decoder->dc->state != DECODE_STATE_START;
|
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.
|
* Try decoding a stream, using plugins matching the stream's MIME type.
|
||||||
|
*
|
||||||
|
* @param tried_r a list of plugins which were tried
|
||||||
*/
|
*/
|
||||||
static bool
|
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;
|
const struct decoder_plugin *plugin;
|
||||||
unsigned int next = 0;
|
unsigned int next = 0;
|
||||||
|
|
||||||
if (is->mime == NULL)
|
if (is->mime == NULL)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
while ((plugin = decoder_plugin_from_mime_type(is->mime, next++)))
|
while ((plugin = decoder_plugin_from_mime_type(is->mime, next++))) {
|
||||||
if (plugin->stream_decode != NULL &&
|
if (plugin->stream_decode == NULL)
|
||||||
decoder_stream_decode(plugin, decoder, is))
|
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;
|
return true;
|
||||||
|
|
||||||
|
*tried_r = g_slist_prepend(*tried_r, deconst_plugin(plugin));
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Try decoding a stream, using plugins matching the stream's URI
|
* Try decoding a stream, using plugins matching the stream's URI
|
||||||
* suffix.
|
* suffix.
|
||||||
|
*
|
||||||
|
* @param tried_r a list of plugins which were tried
|
||||||
*/
|
*/
|
||||||
static bool
|
static bool
|
||||||
decoder_run_stream_suffix(struct decoder *decoder, struct input_stream *is,
|
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 char *suffix = uri_get_suffix(uri);
|
||||||
const struct decoder_plugin *plugin = NULL;
|
const struct decoder_plugin *plugin = NULL;
|
||||||
|
|
||||||
if (suffix == NULL)
|
if (suffix == NULL)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
while ((plugin = decoder_plugin_from_suffix(suffix, plugin)) != NULL)
|
while ((plugin = decoder_plugin_from_suffix(suffix, plugin)) != NULL) {
|
||||||
if (plugin->stream_decode != NULL &&
|
if (plugin->stream_decode == NULL)
|
||||||
decoder_stream_decode(plugin, decoder, is))
|
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;
|
return true;
|
||||||
|
|
||||||
|
*tried_r = g_slist_prepend(*tried_r, deconst_plugin(plugin));
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -231,15 +272,20 @@ decoder_run_stream(struct decoder *decoder, const char *uri)
|
||||||
|
|
||||||
decoder_lock(dc);
|
decoder_lock(dc);
|
||||||
|
|
||||||
|
GSList *tried = NULL;
|
||||||
|
|
||||||
success = dc->command == DECODE_COMMAND_STOP ||
|
success = dc->command == DECODE_COMMAND_STOP ||
|
||||||
/* first we try mime types: */
|
/* 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: */
|
/* 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
|
/* fallback to mp3: this is needed for bastard streams
|
||||||
that don't have a suffix or set the mimeType */
|
that don't have a suffix or set the mimeType */
|
||||||
decoder_run_stream_fallback(decoder, input_stream);
|
decoder_run_stream_fallback(decoder, input_stream);
|
||||||
|
|
||||||
|
g_slist_free(tried);
|
||||||
|
|
||||||
decoder_unlock(dc);
|
decoder_unlock(dc);
|
||||||
input_stream_close(input_stream);
|
input_stream_close(input_stream);
|
||||||
decoder_lock(dc);
|
decoder_lock(dc);
|
||||||
|
|
Loading…
Reference in New Issue