decoder/Thread: repair container decoder support
Catch ENOTDIR exceptions and in that case, try all matching decoder plugins which implement the "container_scan" method. https://bugs.musicpd.org/view.php?id=4561
This commit is contained in:
parent
0abee77e62
commit
aa877a29d7
@ -31,6 +31,7 @@
|
|||||||
#include "input/InputStream.hxx"
|
#include "input/InputStream.hxx"
|
||||||
#include "input/LocalOpen.hxx"
|
#include "input/LocalOpen.hxx"
|
||||||
#include "DecoderList.hxx"
|
#include "DecoderList.hxx"
|
||||||
|
#include "system/Error.hxx"
|
||||||
#include "util/MimeType.hxx"
|
#include "util/MimeType.hxx"
|
||||||
#include "util/UriUtil.hxx"
|
#include "util/UriUtil.hxx"
|
||||||
#include "util/RuntimeError.hxx"
|
#include "util/RuntimeError.hxx"
|
||||||
@ -309,6 +310,44 @@ TryDecoderFile(DecoderBridge &bridge, Path path_fs, const char *suffix,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decode a container file with the given decoder plugin.
|
||||||
|
*
|
||||||
|
* DecoderControl::mutex is not locked by caller.
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
TryContainerDecoder(DecoderBridge &bridge, Path path_fs, const char *suffix,
|
||||||
|
const DecoderPlugin &plugin)
|
||||||
|
{
|
||||||
|
if (plugin.container_scan == nullptr ||
|
||||||
|
plugin.file_decode == nullptr ||
|
||||||
|
!plugin.SupportsSuffix(suffix))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
bridge.error = nullptr;
|
||||||
|
|
||||||
|
DecoderControl &dc = bridge.dc;
|
||||||
|
const ScopeLock protect(dc.mutex);
|
||||||
|
return decoder_file_decode(plugin, bridge, path_fs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decode a container file.
|
||||||
|
*
|
||||||
|
* DecoderControl::mutex is not locked by caller.
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
TryContainerDecoder(DecoderBridge &bridge, Path path_fs, const char *suffix)
|
||||||
|
{
|
||||||
|
return decoder_plugins_try([&bridge, path_fs,
|
||||||
|
suffix](const DecoderPlugin &plugin){
|
||||||
|
return TryContainerDecoder(bridge,
|
||||||
|
path_fs,
|
||||||
|
suffix,
|
||||||
|
plugin);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Try decoding a file.
|
* Try decoding a file.
|
||||||
*
|
*
|
||||||
@ -321,7 +360,20 @@ decoder_run_file(DecoderBridge &bridge, const char *uri_utf8, Path path_fs)
|
|||||||
if (suffix == nullptr)
|
if (suffix == nullptr)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
auto input_stream = decoder_input_stream_open(bridge.dc, path_fs);
|
InputStreamPtr input_stream;
|
||||||
|
|
||||||
|
try {
|
||||||
|
input_stream = decoder_input_stream_open(bridge.dc, path_fs);
|
||||||
|
} catch (const std::system_error &e) {
|
||||||
|
if (IsPathNotFound(e) &&
|
||||||
|
/* ENOTDIR means this may be a path inside a
|
||||||
|
"container" file */
|
||||||
|
TryContainerDecoder(bridge, path_fs, suffix))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
assert(input_stream);
|
assert(input_stream);
|
||||||
|
|
||||||
LoadReplayGain(bridge, *input_stream);
|
LoadReplayGain(bridge, *input_stream);
|
||||||
|
Loading…
Reference in New Issue
Block a user