* Try decoding a file. * * DecoderControl::mutex is not locked by caller. */
| 449 | * DecoderControl::mutex is not locked by caller. |
| 450 | */ |
| 451 | static DecodeResult |
| 452 | decoder_run_file(DecoderBridge &bridge, const char *uri_utf8, Path path_fs) |
| 453 | { |
| 454 | const char *_suffix = PathTraitsUTF8::GetFilenameSuffix(uri_utf8); |
| 455 | if (_suffix == nullptr) |
| 456 | return DecodeResult::NO_PLUGIN; |
| 457 | |
| 458 | const std::string_view suffix{_suffix}; |
| 459 | |
| 460 | InputStreamPtr input_stream; |
| 461 | |
| 462 | try { |
| 463 | input_stream = bridge.OpenLocal(path_fs, uri_utf8); |
| 464 | } catch (const std::system_error &e) { |
| 465 | if (IsPathNotFound(e)) { |
| 466 | /* ENOTDIR means this may be a path inside a |
| 467 | "container" file */ |
| 468 | const auto result = TryContainerDecoder(bridge, path_fs, suffix); |
| 469 | if (IsFinalDecodeResult(result)) |
| 470 | return result; |
| 471 | } |
| 472 | |
| 473 | throw; |
| 474 | } |
| 475 | |
| 476 | assert(input_stream); |
| 477 | |
| 478 | MaybeLoadReplayGain(bridge, *input_stream); |
| 479 | |
| 480 | DecodeResult result = DecodeResult::NO_PLUGIN; |
| 481 | for (const auto &plugin : GetEnabledDecoderPlugins()) { |
| 482 | if (const auto r = TryDecoderFile(bridge, path_fs, suffix, *input_stream, plugin); |
| 483 | r > result) { |
| 484 | result = r; |
| 485 | if (IsFinalDecodeResult(result)) |
| 486 | break; |
| 487 | } |
| 488 | } |
| 489 | |
| 490 | return result; |
| 491 | } |
| 492 | |
| 493 | /** |
| 494 | * Decode a song. |
no test coverage detected