diff --git a/Meta/Lagom/CMakeLists.txt b/Meta/Lagom/CMakeLists.txt index a2d69e6030..b8196b67e8 100644 --- a/Meta/Lagom/CMakeLists.txt +++ b/Meta/Lagom/CMakeLists.txt @@ -492,7 +492,7 @@ if (BUILD_LAGOM) if (NOT EMSCRIPTEN) # LibELF is part of LibC in SerenityOS builds, but not in Lagom. add_executable(file ../../Userland/Utilities/file.cpp) - target_link_libraries(file LibCompress LibCore LibELF LibGfx LibIPC LibMain) + target_link_libraries(file LibAudio LibCompress LibCore LibELF LibGfx LibIPC LibMain) endif() add_executable(gml-format ../../Userland/Utilities/gml-format.cpp) diff --git a/Userland/BuggieBox/CMakeLists.txt b/Userland/BuggieBox/CMakeLists.txt index 200daa5142..fcd294ed8b 100644 --- a/Userland/BuggieBox/CMakeLists.txt +++ b/Userland/BuggieBox/CMakeLists.txt @@ -41,7 +41,7 @@ set(utility_srcs serenity_bin(BuggieBox) target_sources(BuggieBox PRIVATE main.cpp) -target_link_libraries(BuggieBox PRIVATE LibMain LibShell LibCompress LibCore LibCrypto LibGfx LibLine LibRegex) +target_link_libraries(BuggieBox PRIVATE LibMain LibShell LibCompress LibCore LibCrypto LibGfx LibLine LibRegex LibAudio) foreach(file IN LISTS utility_srcs) buggiebox_utility(${file}) diff --git a/Userland/Utilities/CMakeLists.txt b/Userland/Utilities/CMakeLists.txt index 621e9640e5..b13de2e832 100644 --- a/Userland/Utilities/CMakeLists.txt +++ b/Userland/Utilities/CMakeLists.txt @@ -87,7 +87,7 @@ target_link_libraries(diff PRIVATE LibDiff) target_link_libraries(disasm PRIVATE LibX86) target_link_libraries(expr PRIVATE LibRegex) target_link_libraries(fdtdump PRIVATE LibDeviceTree) -target_link_libraries(file PRIVATE LibGfx LibIPC LibCompress) +target_link_libraries(file PRIVATE LibGfx LibIPC LibCompress LibAudio) target_link_libraries(functrace PRIVATE LibDebug LibX86) target_link_libraries(gml-format PRIVATE LibGUI) target_link_libraries(grep PRIVATE LibRegex) diff --git a/Userland/Utilities/file.cpp b/Userland/Utilities/file.cpp index c574e1f20a..eb0d9b5ebc 100644 --- a/Userland/Utilities/file.cpp +++ b/Userland/Utilities/file.cpp @@ -5,6 +5,7 @@ */ #include +#include #include #include #include @@ -51,6 +52,48 @@ static Optional image_details(StringView description, StringVi return builder.to_deprecated_string(); } +static Optional audio_details(StringView description, StringView path) +{ + auto loader_or_error = Audio::Loader::create(path); + if (loader_or_error.is_error()) + return {}; + + auto loader = loader_or_error.release_value(); + StringBuilder builder; + builder.appendff("{}, {} Hz, {}-bit {}, {} samples ({} s)", + description, + loader->sample_rate(), + loader->bits_per_sample(), + loader->num_channels() == 1 ? "Mono" : "Stereo", + loader->total_samples(), + loader->total_samples() / loader->sample_rate()); + auto metadata = loader->metadata(); + Vector metadata_parts; + if (metadata.title.has_value()) { + // FIXME: Use “pretty quotation” once our terminal fonts support these characters. + if (auto title_text = String::formatted("\"{}\"", metadata.title.value_or({})); !title_text.is_error()) { + // We intentionally discard the error, because not printing part of the metadata due to OOM is not a problem. + (void)metadata_parts.try_append(title_text.release_value()); + } + } + if (metadata.album.has_value()) { + if (auto album_text = String::formatted("(Album: {})", metadata.album.value_or({})); !album_text.is_error()) + (void)metadata_parts.try_append(album_text.release_value()); + } + if (auto all_artists = metadata.all_artists(); !all_artists.is_error() && all_artists.value().has_value()) { + if (auto artist_text = String::formatted("by {}", all_artists.release_value().release_value()); !artist_text.is_error()) + (void)metadata_parts.try_append(artist_text.release_value()); + } + + if (!metadata_parts.is_empty()) { + // New line for the metadata. + builder.append_code_point('\n'); + builder.join(" "sv, metadata_parts); + } + + return builder.to_deprecated_string(); +} + static Optional gzip_details(StringView description, StringView path) { auto file_or_error = Core::MappedFile::map(path); @@ -113,11 +156,11 @@ static Optional elf_details(StringView description, StringView __ENUMERATE_MIME_TYPE_DESCRIPTION("application/tar"sv, "tape archive"sv, description_only) \ __ENUMERATE_MIME_TYPE_DESCRIPTION("application/wasm"sv, "WebAssembly bytecode"sv, description_only) \ __ENUMERATE_MIME_TYPE_DESCRIPTION("application/x-7z-compressed"sv, "7-Zip archive"sv, description_only) \ - __ENUMERATE_MIME_TYPE_DESCRIPTION("audio/flac"sv, "FLAC audio"sv, description_only) \ - __ENUMERATE_MIME_TYPE_DESCRIPTION("audio/midi"sv, "MIDI notes"sv, description_only) \ - __ENUMERATE_MIME_TYPE_DESCRIPTION("audio/mpeg"sv, "MP3 audio"sv, description_only) \ - __ENUMERATE_MIME_TYPE_DESCRIPTION("audio/qoa"sv, "Quite OK Audio"sv, description_only) \ - __ENUMERATE_MIME_TYPE_DESCRIPTION("audio/wave"sv, "WAVE audio"sv, description_only) \ + __ENUMERATE_MIME_TYPE_DESCRIPTION("audio/flac"sv, "FLAC audio"sv, audio_details) \ + __ENUMERATE_MIME_TYPE_DESCRIPTION("audio/midi"sv, "MIDI notes"sv, audio_details) \ + __ENUMERATE_MIME_TYPE_DESCRIPTION("audio/mpeg"sv, "MP3 audio"sv, audio_details) \ + __ENUMERATE_MIME_TYPE_DESCRIPTION("audio/qoa"sv, "Quite OK Audio"sv, audio_details) \ + __ENUMERATE_MIME_TYPE_DESCRIPTION("audio/wave"sv, "WAVE audio"sv, audio_details) \ __ENUMERATE_MIME_TYPE_DESCRIPTION("extra/blender"sv, "Blender project file"sv, description_only) \ __ENUMERATE_MIME_TYPE_DESCRIPTION("extra/elf"sv, "ELF"sv, elf_details) \ __ENUMERATE_MIME_TYPE_DESCRIPTION("extra/ext"sv, "ext filesystem"sv, description_only) \