diff options
author | Lucas CHOLLET <lucas.chollet@free.fr> | 2022-10-04 01:07:18 +0200 |
---|---|---|
committer | Andrew Kaster <andrewdkaster@gmail.com> | 2022-11-13 18:51:18 -0700 |
commit | 7649feb26f83f35f4ea3eb42849df8b7a389cc12 (patch) | |
tree | a8f7bd9eed49b268cc01a47feb730e9aff92cc81 /Userland/Applications | |
parent | 27539440df543d50098dbd6b30912ebd2a33165f (diff) | |
download | serenity-7649feb26f83f35f4ea3eb42849df8b7a389cc12.zip |
SoundPlayer: Load cover image from music files
When the visualization is set to "Album Cover", the player will now try
to load the embedded image. On failure, it defaults to a "Cover" image
file in the directory.
In Player::play_file_path, file_name_changed now needs to be executed
after that the loader have been set, to get the correct image.
Diffstat (limited to 'Userland/Applications')
7 files changed, 55 insertions, 10 deletions
diff --git a/Userland/Applications/SoundPlayer/AlbumCoverVisualizationWidget.cpp b/Userland/Applications/SoundPlayer/AlbumCoverVisualizationWidget.cpp index ceb468e6cd..152fa32b67 100644 --- a/Userland/Applications/SoundPlayer/AlbumCoverVisualizationWidget.cpp +++ b/Userland/Applications/SoundPlayer/AlbumCoverVisualizationWidget.cpp @@ -12,13 +12,19 @@ #include <LibGUI/Painter.h> #include <LibGfx/Rect.h> +AlbumCoverVisualizationWidget::AlbumCoverVisualizationWidget(Function<RefPtr<Gfx::Bitmap>()> get_file_cover_from_player) + : m_get_file_cover_from_player(move(get_file_cover_from_player)) +{ +} + void AlbumCoverVisualizationWidget::paint_event(GUI::PaintEvent& event) { Frame::paint_event(event); GUI::Painter painter(*this); - if (m_album_cover) { - auto album_cover_rect = m_album_cover->rect(); + auto const& cover = m_file_cover ? m_file_cover : m_album_cover; + if (cover) { + auto album_cover_rect = cover->rect(); auto height_ratio = frame_inner_rect().height() / (float)album_cover_rect.height(); auto width_ratio = frame_inner_rect().width() / (float)album_cover_rect.width(); @@ -27,7 +33,7 @@ void AlbumCoverVisualizationWidget::paint_event(GUI::PaintEvent& event) Gfx::IntRect fitted_rect = { 0, 0, (int)(album_cover_rect.width() * scale), (int)(album_cover_rect.height() * scale) }; fitted_rect.center_within(frame_inner_rect()); - painter.draw_scaled_bitmap(fitted_rect, *m_album_cover, m_album_cover->rect(), 1.0f); + painter.draw_scaled_bitmap(fitted_rect, *cover, cover->rect(), 1.0f); } else { if (!m_serenity_bg) m_serenity_bg = Gfx::Bitmap::try_load_from_file("/res/wallpapers/sunset-retro.png"sv).release_value_but_fixme_should_propagate_errors(); @@ -51,6 +57,12 @@ ErrorOr<NonnullRefPtr<Gfx::Bitmap>> AlbumCoverVisualizationWidget::get_album_cov void AlbumCoverVisualizationWidget::start_new_file(StringView filename) { + if (m_get_file_cover_from_player) + m_file_cover = m_get_file_cover_from_player(); + + if (m_file_cover) + return; + auto album_cover_or_error = get_album_cover(filename); if (album_cover_or_error.is_error()) m_album_cover = nullptr; diff --git a/Userland/Applications/SoundPlayer/AlbumCoverVisualizationWidget.h b/Userland/Applications/SoundPlayer/AlbumCoverVisualizationWidget.h index 48aeb357ba..fb30e1499f 100644 --- a/Userland/Applications/SoundPlayer/AlbumCoverVisualizationWidget.h +++ b/Userland/Applications/SoundPlayer/AlbumCoverVisualizationWidget.h @@ -14,6 +14,7 @@ class AlbumCoverVisualizationWidget final : public VisualizationWidget { C_OBJECT(AlbumCoverVisualizationWidget) public: + AlbumCoverVisualizationWidget(Function<RefPtr<Gfx::Bitmap>()> get_file_cover_from_player); ~AlbumCoverVisualizationWidget() override = default; void start_new_file(StringView) override; @@ -23,6 +24,9 @@ private: AlbumCoverVisualizationWidget() = default; ErrorOr<NonnullRefPtr<Gfx::Bitmap>> get_album_cover(StringView const filename); + Function<RefPtr<Gfx::Bitmap>()> m_get_file_cover_from_player; + RefPtr<Gfx::Bitmap> m_serenity_bg; RefPtr<Gfx::Bitmap> m_album_cover; + RefPtr<Gfx::Bitmap> m_file_cover; }; diff --git a/Userland/Applications/SoundPlayer/CMakeLists.txt b/Userland/Applications/SoundPlayer/CMakeLists.txt index 325b95b7f9..173a34b5e2 100644 --- a/Userland/Applications/SoundPlayer/CMakeLists.txt +++ b/Userland/Applications/SoundPlayer/CMakeLists.txt @@ -19,4 +19,4 @@ set(SOURCES ) serenity_app(SoundPlayer ICON app-sound-player) -target_link_libraries(SoundPlayer PRIVATE LibAudio LibCore LibDSP LibGfx LibGUI LibIPC LibMain LibThreading) +target_link_libraries(SoundPlayer PRIVATE LibAudio LibCore LibDSP LibGfx LibGUI LibIPC LibMain LibThreading LibImageDecoderClient) diff --git a/Userland/Applications/SoundPlayer/Player.cpp b/Userland/Applications/SoundPlayer/Player.cpp index 75bb45b876..47f1cbb0fd 100644 --- a/Userland/Applications/SoundPlayer/Player.cpp +++ b/Userland/Applications/SoundPlayer/Player.cpp @@ -6,6 +6,7 @@ */ #include "Player.h" +#include <LibAudio/FlacLoader.h> #include <LibCore/File.h> Player::Player(Audio::ConnectionToServer& audio_client_connection) @@ -63,9 +64,9 @@ void Player::play_file_path(String const& path) m_loaded_filename = path; - file_name_changed(path); total_samples_changed(loader->total_samples()); m_playback_manager.set_loader(move(loader)); + file_name_changed(path); play(); } @@ -156,3 +157,8 @@ void Player::seek(int sample) { m_playback_manager.seek(sample); } + +Vector<Audio::PictureData> const& Player::pictures() const +{ + return m_playback_manager.loader()->pictures(); +} diff --git a/Userland/Applications/SoundPlayer/Player.h b/Userland/Applications/SoundPlayer/Player.h index cd8872c590..ec2ef78660 100644 --- a/Userland/Applications/SoundPlayer/Player.h +++ b/Userland/Applications/SoundPlayer/Player.h @@ -11,6 +11,7 @@ #include "Playlist.h" #include "PlaylistWidget.h" #include <AK/RefPtr.h> +#include <LibAudio/GenericTypes.h> #include <LibAudio/Sample.h> class Player { @@ -75,6 +76,8 @@ public: virtual void total_samples_changed(int) = 0; virtual void sound_buffer_played(FixedArray<Audio::Sample> const&, [[maybe_unused]] int sample_rate, [[maybe_unused]] int samples_played) = 0; + Vector<Audio::PictureData> const& pictures() const; + protected: void done_initializing() { diff --git a/Userland/Applications/SoundPlayer/SoundPlayerWidgetAdvancedView.h b/Userland/Applications/SoundPlayer/SoundPlayerWidgetAdvancedView.h index 9c79ee720f..e17fb0f4ed 100644 --- a/Userland/Applications/SoundPlayer/SoundPlayerWidgetAdvancedView.h +++ b/Userland/Applications/SoundPlayer/SoundPlayerWidgetAdvancedView.h @@ -25,12 +25,12 @@ public: void set_nonlinear_volume_slider(bool nonlinear); void set_playlist_visible(bool visible); - template<typename T> - void set_visualization() + template<typename T, typename... Args> + void set_visualization(Args... args) { m_visualization->remove_from_parent(); update(); - auto new_visualization = T::construct(); + auto new_visualization = T::construct(move(args)...); m_player_view->insert_child_before(new_visualization, *static_cast<Core::Object*>(m_playback_progress_slider.ptr())); m_visualization = new_visualization; if (!loaded_filename().is_empty()) diff --git a/Userland/Applications/SoundPlayer/main.cpp b/Userland/Applications/SoundPlayer/main.cpp index fc91cac584..f390439817 100644 --- a/Userland/Applications/SoundPlayer/main.cpp +++ b/Userland/Applications/SoundPlayer/main.cpp @@ -5,12 +5,16 @@ * SPDX-License-Identifier: BSD-2-Clause */ +// FIXME: LibIPC Decoder and Encoder are sensitive to include order here +#include <LibImageDecoderClient/Client.h> + #include "AlbumCoverVisualizationWidget.h" #include "BarsVisualizationWidget.h" #include "Player.h" #include "SampleWidget.h" #include "SoundPlayerWidgetAdvancedView.h" #include <LibAudio/ConnectionToServer.h> +#include <LibAudio/FlacLoader.h> #include <LibCore/System.h> #include <LibGUI/Action.h> #include <LibGUI/ActionGroup.h> @@ -21,7 +25,6 @@ #include <LibGUI/Window.h> #include <LibGfx/CharacterBitmap.h> #include <LibMain/Main.h> -#include <stdio.h> ErrorOr<int> serenity_main(Main::Arguments arguments) { @@ -29,6 +32,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments) auto app = TRY(GUI::Application::try_create(arguments)); auto audio_client = TRY(Audio::ConnectionToServer::try_create()); + auto decoder_client = TRY(ImageDecoderClient::Client::try_create()); TRY(Core::System::pledge("stdio recvfd sendfd rpath thread")); @@ -125,7 +129,23 @@ ErrorOr<int> serenity_main(Main::Arguments arguments) visualization_actions.add_action(samples); auto album_cover_visualization = GUI::Action::create_checkable("&Album Cover", [&](auto&) { - static_cast<SoundPlayerWidgetAdvancedView*>(player)->set_visualization<AlbumCoverVisualizationWidget>(); + auto get_image_from_music_file = [&player, &decoder_client]() -> RefPtr<Gfx::Bitmap> { + auto const& pictures = player->pictures(); + + if (pictures.is_empty()) + return {}; + + // FIXME: We randomly select the first picture available for the track, + // We might want to hardcode or let the user set a preference. + auto decoded_image_or_error = decoder_client->decode_image(pictures[0].data); + if (!decoded_image_or_error.has_value()) + return {}; + + auto const decoded_image = decoded_image_or_error.release_value(); + return decoded_image.frames[0].bitmap; + }; + + static_cast<SoundPlayerWidgetAdvancedView*>(player)->set_visualization<AlbumCoverVisualizationWidget>(get_image_from_music_file); }); TRY(visualization_menu->try_add_action(album_cover_visualization)); visualization_actions.add_action(album_cover_visualization); |