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:
		| @@ -31,6 +31,7 @@ | ||||
| #include "input/InputStream.hxx" | ||||
| #include "input/LocalOpen.hxx" | ||||
| #include "DecoderList.hxx" | ||||
| #include "system/Error.hxx" | ||||
| #include "util/MimeType.hxx" | ||||
| #include "util/UriUtil.hxx" | ||||
| #include "util/RuntimeError.hxx" | ||||
| @@ -309,6 +310,44 @@ TryDecoderFile(DecoderBridge &bridge, Path path_fs, const char *suffix, | ||||
| 		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. | ||||
|  * | ||||
| @@ -321,7 +360,20 @@ decoder_run_file(DecoderBridge &bridge, const char *uri_utf8, Path path_fs) | ||||
| 	if (suffix == nullptr) | ||||
| 		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); | ||||
|  | ||||
| 	LoadReplayGain(bridge, *input_stream); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Max Kellermann
					Max Kellermann