mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 20:42:43 +00:00 
			
		
		
		
	SoundPlayer: Add samplerate variable to visualizations
also fix conflict
This commit is contained in:
		
							parent
							
								
									2e28b8ebcc
								
							
						
					
					
						commit
						fd126578d9
					
				
					 12 changed files with 51 additions and 311 deletions
				
			
		|  | @ -49,8 +49,7 @@ void BarsVisualizationWidget::paint_event(GUI::PaintEvent& event) | ||||||
|     fft(m_sample_buffer, false); |     fft(m_sample_buffer, false); | ||||||
|     double max = sqrt(m_sample_count * 2); |     double max = sqrt(m_sample_count * 2); | ||||||
| 
 | 
 | ||||||
|     //TODO: don't hardcode this!
 |     double freq_bin = m_samplerate / m_sample_count; | ||||||
|     double freq_bin = 44100 / m_sample_count; |  | ||||||
| 
 | 
 | ||||||
|     constexpr int group_count = 60; |     constexpr int group_count = 60; | ||||||
|     Vector<double, group_count> groups; |     Vector<double, group_count> groups; | ||||||
|  | @ -73,7 +72,7 @@ void BarsVisualizationWidget::paint_event(GUI::PaintEvent& event) | ||||||
| 
 | 
 | ||||||
|     const int horizontal_margin = 30; |     const int horizontal_margin = 30; | ||||||
|     const int top_vertical_margin = 15; |     const int top_vertical_margin = 15; | ||||||
|     const int pixels_inbetween_groups = 5; |     const int pixels_inbetween_groups = frame_inner_rect().width() > 350 ? 5 : 2; | ||||||
|     int pixel_per_group_width = (frame_inner_rect().width() - horizontal_margin * 2 - pixels_inbetween_groups * (group_count - 1)) / group_count; |     int pixel_per_group_width = (frame_inner_rect().width() - horizontal_margin * 2 - pixels_inbetween_groups * (group_count - 1)) / group_count; | ||||||
|     int max_height = frame_inner_rect().height() - top_vertical_margin; |     int max_height = frame_inner_rect().height() - top_vertical_margin; | ||||||
|     int current_xpos = horizontal_margin; |     int current_xpos = horizontal_margin; | ||||||
|  | @ -146,3 +145,7 @@ void BarsVisualizationWidget::mousedown_event(GUI::MouseEvent& event) | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void BarsVisualizationWidget::set_samplerate(int samplerate) | ||||||
|  | { | ||||||
|  |     m_samplerate = samplerate; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -38,10 +38,12 @@ class BarsVisualizationWidget final : public GUI::Frame | ||||||
| public: | public: | ||||||
|     ~BarsVisualizationWidget() override; |     ~BarsVisualizationWidget() override; | ||||||
|     void set_buffer(RefPtr<Audio::Buffer> buffer) override; |     void set_buffer(RefPtr<Audio::Buffer> buffer) override; | ||||||
|  |     void set_samplerate(int samplerate) override; | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     void set_buffer(RefPtr<Audio::Buffer> buffer, int samples_to_use); |  | ||||||
|     BarsVisualizationWidget(); |     BarsVisualizationWidget(); | ||||||
|  |     void set_buffer(RefPtr<Audio::Buffer> buffer, int samples_to_use); | ||||||
|  | 
 | ||||||
|     void paint_event(GUI::PaintEvent&) override; |     void paint_event(GUI::PaintEvent&) override; | ||||||
|     void mousedown_event(GUI::MouseEvent& event) override; |     void mousedown_event(GUI::MouseEvent& event) override; | ||||||
| 
 | 
 | ||||||
|  | @ -49,6 +51,7 @@ private: | ||||||
|     Vector<int> m_gfx_falling_bars; |     Vector<int> m_gfx_falling_bars; | ||||||
|     int m_last_id; |     int m_last_id; | ||||||
|     int m_sample_count; |     int m_sample_count; | ||||||
|  |     int m_samplerate; | ||||||
|     bool m_is_using_last; |     bool m_is_using_last; | ||||||
|     bool m_adjust_frequencies; |     bool m_adjust_frequencies; | ||||||
|     RefPtr<GUI::Menu> m_context_menu; |     RefPtr<GUI::Menu> m_context_menu; | ||||||
|  |  | ||||||
|  | @ -2,7 +2,6 @@ set(SOURCES | ||||||
|     main.cpp |     main.cpp | ||||||
|     PlaybackManager.cpp |     PlaybackManager.cpp | ||||||
|     SampleWidget.cpp |     SampleWidget.cpp | ||||||
|     SoundPlayerWidget.cpp |  | ||||||
|     SoundPlayerWidgetAdvancedView.cpp |     SoundPlayerWidgetAdvancedView.cpp | ||||||
|     BarsVisualizationWidget.cpp |     BarsVisualizationWidget.cpp | ||||||
|     AudioAlgorithms.cpp |     AudioAlgorithms.cpp | ||||||
|  |  | ||||||
|  | @ -28,10 +28,10 @@ | ||||||
| 
 | 
 | ||||||
| #include <LibGUI/Slider.h> | #include <LibGUI/Slider.h> | ||||||
| 
 | 
 | ||||||
| class Slider final : public GUI::Slider { | class AutoSlider final : public GUI::Slider { | ||||||
|     C_OBJECT(Slider) |     C_OBJECT(AutoSlider) | ||||||
| public: | public: | ||||||
|     ~Slider() override = default; |     ~AutoSlider() override = default; | ||||||
|     Function<void(int)> on_knob_released; |     Function<void(int)> on_knob_released; | ||||||
|     void set_value(int value) |     void set_value(int value) | ||||||
|     { |     { | ||||||
|  | @ -40,7 +40,7 @@ public: | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| protected: | protected: | ||||||
|     Slider(Orientation orientation) |     AutoSlider(Orientation orientation) | ||||||
|         : GUI::Slider(orientation) |         : GUI::Slider(orientation) | ||||||
|     { |     { | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -172,13 +172,10 @@ void PlaybackManager::next_buffer() | ||||||
|     remove_dead_buffers(); |     remove_dead_buffers(); | ||||||
|     if (!m_next_buffer) { |     if (!m_next_buffer) { | ||||||
|         if (!m_connection->get_remaining_samples() && !m_paused) { |         if (!m_connection->get_remaining_samples() && !m_paused) { | ||||||
|             dbgln("Exhausted samples :^)"); |  | ||||||
|             if (m_loop) |  | ||||||
|                 seek(0); |  | ||||||
|             else |  | ||||||
|             stop(); |             stop(); | ||||||
|  |             if (on_finished_playing) | ||||||
|  |                 on_finished_playing(); | ||||||
|         } |         } | ||||||
| 
 |  | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -57,6 +57,7 @@ public: | ||||||
| 
 | 
 | ||||||
|     Function<void()> on_update; |     Function<void()> on_update; | ||||||
|     Function<void(Audio::Buffer&)> on_load_sample_buffer; |     Function<void(Audio::Buffer&)> on_load_sample_buffer; | ||||||
|  |     Function<void()> on_finished_playing; | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     void next_buffer(); |     void next_buffer(); | ||||||
|  |  | ||||||
|  | @ -1,206 +0,0 @@ | ||||||
| /*
 |  | ||||||
|  * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> |  | ||||||
|  * All rights reserved. |  | ||||||
|  * |  | ||||||
|  * Redistribution and use in source and binary forms, with or without |  | ||||||
|  * modification, are permitted provided that the following conditions are met: |  | ||||||
|  * |  | ||||||
|  * 1. Redistributions of source code must retain the above copyright notice, this |  | ||||||
|  *    list of conditions and the following disclaimer. |  | ||||||
|  * |  | ||||||
|  * 2. Redistributions in binary form must reproduce the above copyright notice, |  | ||||||
|  *    this list of conditions and the following disclaimer in the documentation |  | ||||||
|  *    and/or other materials provided with the distribution. |  | ||||||
|  * |  | ||||||
|  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |  | ||||||
|  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |  | ||||||
|  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |  | ||||||
|  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE |  | ||||||
|  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |  | ||||||
|  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |  | ||||||
|  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |  | ||||||
|  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |  | ||||||
|  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |  | ||||||
|  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| #include "SoundPlayerWidget.h" |  | ||||||
| #include "Common.h" |  | ||||||
| #include <AK/StringBuilder.h> |  | ||||||
| #include <LibCore/MimeData.h> |  | ||||||
| #include <LibGUI/BoxLayout.h> |  | ||||||
| #include <LibGUI/Button.h> |  | ||||||
| #include <LibGUI/Label.h> |  | ||||||
| #include <LibGUI/MessageBox.h> |  | ||||||
| 
 |  | ||||||
| SoundPlayerWidget::SoundPlayerWidget(GUI::Window& window, PlayerState& state) |  | ||||||
|     : Player(state) |  | ||||||
|     , m_window(window) |  | ||||||
| { |  | ||||||
|     window.set_resizable(false); |  | ||||||
|     window.resize(350, 140); |  | ||||||
| 
 |  | ||||||
|     set_fill_with_background_color(true); |  | ||||||
|     set_layout<GUI::VerticalBoxLayout>(); |  | ||||||
|     layout()->set_margins({ 2, 2, 2, 2 }); |  | ||||||
| 
 |  | ||||||
|     auto& status_widget = add<GUI::Widget>(); |  | ||||||
|     status_widget.set_fill_with_background_color(true); |  | ||||||
|     status_widget.set_layout<GUI::HorizontalBoxLayout>(); |  | ||||||
| 
 |  | ||||||
|     m_elapsed = status_widget.add<GUI::Label>(); |  | ||||||
|     m_elapsed->set_frame_shape(Gfx::FrameShape::Container); |  | ||||||
|     m_elapsed->set_frame_shadow(Gfx::FrameShadow::Sunken); |  | ||||||
|     m_elapsed->set_frame_thickness(2); |  | ||||||
|     m_elapsed->set_fixed_width(80); |  | ||||||
| 
 |  | ||||||
|     auto& sample_widget_container = status_widget.add<GUI::Widget>(); |  | ||||||
|     sample_widget_container.set_layout<GUI::HorizontalBoxLayout>(); |  | ||||||
| 
 |  | ||||||
|     m_sample_widget = sample_widget_container.add<SampleWidget>(); |  | ||||||
| 
 |  | ||||||
|     m_remaining = status_widget.add<GUI::Label>(); |  | ||||||
|     m_remaining->set_frame_shape(Gfx::FrameShape::Container); |  | ||||||
|     m_remaining->set_frame_shadow(Gfx::FrameShadow::Sunken); |  | ||||||
|     m_remaining->set_frame_thickness(2); |  | ||||||
|     m_remaining->set_fixed_width(80); |  | ||||||
| 
 |  | ||||||
|     m_slider = add<Slider>(Orientation::Horizontal); |  | ||||||
|     m_slider->set_min(0); |  | ||||||
|     m_slider->set_enabled(has_loaded_file()); |  | ||||||
|     m_slider->on_knob_released = [&](int value) { manager().seek(denormalize_rate(value)); }; |  | ||||||
| 
 |  | ||||||
|     auto& control_widget = add<GUI::Widget>(); |  | ||||||
|     control_widget.set_fill_with_background_color(true); |  | ||||||
|     control_widget.set_layout<GUI::HorizontalBoxLayout>(); |  | ||||||
|     control_widget.set_fixed_height(30); |  | ||||||
|     control_widget.layout()->set_margins({ 10, 2, 10, 2 }); |  | ||||||
|     control_widget.layout()->set_spacing(10); |  | ||||||
| 
 |  | ||||||
|     m_play = control_widget.add<GUI::Button>(); |  | ||||||
|     m_play->set_icon(has_loaded_file() ? *m_play_icon : *m_pause_icon); |  | ||||||
|     m_play->set_enabled(has_loaded_file()); |  | ||||||
|     m_play->on_click = [this](auto) { |  | ||||||
|         bool paused = manager().toggle_pause(); |  | ||||||
|         set_paused(paused); |  | ||||||
|         m_play->set_icon(paused ? *m_play_icon : *m_pause_icon); |  | ||||||
|     }; |  | ||||||
| 
 |  | ||||||
|     m_stop = control_widget.add<GUI::Button>(); |  | ||||||
|     m_stop->set_enabled(has_loaded_file()); |  | ||||||
|     m_stop->set_icon(Gfx::Bitmap::load_from_file("/res/icons/16x16/stop.png")); |  | ||||||
|     m_stop->on_click = [this](auto) { |  | ||||||
|         manager().stop(); |  | ||||||
|         set_stopped(true); |  | ||||||
|     }; |  | ||||||
| 
 |  | ||||||
|     m_status = add<GUI::Label>(); |  | ||||||
|     m_status->set_frame_shape(Gfx::FrameShape::Box); |  | ||||||
|     m_status->set_frame_shadow(Gfx::FrameShadow::Raised); |  | ||||||
|     m_status->set_frame_thickness(4); |  | ||||||
|     m_status->set_text_alignment(Gfx::TextAlignment::CenterLeft); |  | ||||||
|     m_status->set_fixed_height(18); |  | ||||||
|     m_status->set_text(has_loaded_file() ? loaded_filename() : "No file open!"); |  | ||||||
| 
 |  | ||||||
|     update_position(0); |  | ||||||
| 
 |  | ||||||
|     manager().on_update = [&]() { update_ui(); }; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| SoundPlayerWidget::~SoundPlayerWidget() |  | ||||||
| { |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void SoundPlayerWidget::open_file(StringView path) |  | ||||||
| { |  | ||||||
|     NonnullRefPtr<Audio::Loader> loader = Audio::Loader::create(path); |  | ||||||
|     if (loader->has_error() || !loader->sample_rate()) { |  | ||||||
|         const String error_string = loader->error_string(); |  | ||||||
|         GUI::MessageBox::show(window(), |  | ||||||
|             String::formatted("Failed to load audio file: {} ({})", path, error_string.is_null() ? "Unknown error" : error_string), |  | ||||||
|             "Filetype error", GUI::MessageBox::Type::Error); |  | ||||||
|         return; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     m_sample_ratio = PLAYBACK_MANAGER_RATE / static_cast<float>(loader->sample_rate()); |  | ||||||
| 
 |  | ||||||
|     m_slider->set_max(normalize_rate(static_cast<int>(loader->total_samples()))); |  | ||||||
|     m_slider->set_enabled(true); |  | ||||||
|     m_play->set_enabled(true); |  | ||||||
|     m_stop->set_enabled(true); |  | ||||||
| 
 |  | ||||||
|     m_window.set_title(String::formatted("{} - SoundPlayer", loader->file()->filename())); |  | ||||||
|     m_status->set_text(String::formatted( |  | ||||||
|         "Sample rate {}Hz, {} channel(s), {} bits per sample", |  | ||||||
|         loader->sample_rate(), |  | ||||||
|         loader->num_channels(), |  | ||||||
|         loader->bits_per_sample())); |  | ||||||
| 
 |  | ||||||
|     manager().set_loader(move(loader)); |  | ||||||
|     update_position(0); |  | ||||||
|     set_has_loaded_file(true); |  | ||||||
|     set_loaded_filename(path); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void SoundPlayerWidget::drop_event(GUI::DropEvent& event) |  | ||||||
| { |  | ||||||
|     event.accept(); |  | ||||||
|     window()->move_to_front(); |  | ||||||
| 
 |  | ||||||
|     if (event.mime_data().has_urls()) { |  | ||||||
|         auto urls = event.mime_data().urls(); |  | ||||||
|         if (urls.is_empty()) |  | ||||||
|             return; |  | ||||||
|         open_file(urls.first().path()); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int SoundPlayerWidget::normalize_rate(int rate) const |  | ||||||
| { |  | ||||||
|     return static_cast<int>(rate * m_sample_ratio); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int SoundPlayerWidget::denormalize_rate(int rate) const |  | ||||||
| { |  | ||||||
|     return static_cast<int>(rate / m_sample_ratio); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void SoundPlayerWidget::update_ui() |  | ||||||
| { |  | ||||||
|     m_sample_widget->set_buffer(manager().current_buffer()); |  | ||||||
|     m_play->set_icon(manager().is_paused() ? *m_play_icon : *m_pause_icon); |  | ||||||
|     update_position(manager().connection()->get_played_samples()); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void SoundPlayerWidget::update_position(const int position) |  | ||||||
| { |  | ||||||
|     int total_norm_samples = position + normalize_rate(manager().last_seek()); |  | ||||||
|     float seconds = (total_norm_samples / static_cast<float>(PLAYBACK_MANAGER_RATE)); |  | ||||||
|     float remaining_seconds = manager().total_length() - seconds; |  | ||||||
| 
 |  | ||||||
|     m_elapsed->set_text(String::formatted( |  | ||||||
|         "Elapsed:\n{}:{:02}.{:02}", |  | ||||||
|         static_cast<int>(seconds / 60), |  | ||||||
|         static_cast<int>(seconds) % 60, |  | ||||||
|         static_cast<int>(seconds * 100) % 100)); |  | ||||||
| 
 |  | ||||||
|     m_remaining->set_text(String::formatted( |  | ||||||
|         "Remaining:\n{}:{:02}.{:02}", |  | ||||||
|         static_cast<int>(remaining_seconds / 60), |  | ||||||
|         static_cast<int>(remaining_seconds) % 60, |  | ||||||
|         static_cast<int>(remaining_seconds * 100) % 100)); |  | ||||||
| 
 |  | ||||||
|     m_slider->set_value(total_norm_samples); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void SoundPlayerWidget::hide_scope(bool hide) |  | ||||||
| { |  | ||||||
|     m_sample_widget->set_visible(!hide); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void SoundPlayerWidget::play() |  | ||||||
| { |  | ||||||
|     manager().play(); |  | ||||||
|     set_paused(false); |  | ||||||
|     set_stopped(false); |  | ||||||
| } |  | ||||||
|  | @ -1,70 +0,0 @@ | ||||||
| /*
 |  | ||||||
|  * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> |  | ||||||
|  * All rights reserved. |  | ||||||
|  * |  | ||||||
|  * Redistribution and use in source and binary forms, with or without |  | ||||||
|  * modification, are permitted provided that the following conditions are met: |  | ||||||
|  * |  | ||||||
|  * 1. Redistributions of source code must retain the above copyright notice, this |  | ||||||
|  *    list of conditions and the following disclaimer. |  | ||||||
|  * |  | ||||||
|  * 2. Redistributions in binary form must reproduce the above copyright notice, |  | ||||||
|  *    this list of conditions and the following disclaimer in the documentation |  | ||||||
|  *    and/or other materials provided with the distribution. |  | ||||||
|  * |  | ||||||
|  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |  | ||||||
|  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |  | ||||||
|  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |  | ||||||
|  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE |  | ||||||
|  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |  | ||||||
|  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |  | ||||||
|  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |  | ||||||
|  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |  | ||||||
|  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |  | ||||||
|  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| #pragma once |  | ||||||
| 
 |  | ||||||
| #include "Common.h" |  | ||||||
| #include "PlaybackManager.h" |  | ||||||
| #include "Player.h" |  | ||||||
| #include "SampleWidget.h" |  | ||||||
| #include <AK/NonnullRefPtr.h> |  | ||||||
| #include <LibGUI/Button.h> |  | ||||||
| #include <LibGUI/Label.h> |  | ||||||
| #include <LibGUI/Widget.h> |  | ||||||
| #include <LibGUI/Window.h> |  | ||||||
| 
 |  | ||||||
| class SoundPlayerWidget final : public GUI::Widget |  | ||||||
|     , public Player { |  | ||||||
|     C_OBJECT(SoundPlayerWidget) |  | ||||||
| public: |  | ||||||
|     ~SoundPlayerWidget() override; |  | ||||||
|     void open_file(StringView path) override; |  | ||||||
|     void play() override; |  | ||||||
|     void hide_scope(bool); |  | ||||||
| 
 |  | ||||||
| private: |  | ||||||
|     explicit SoundPlayerWidget(GUI::Window& window, PlayerState& state); |  | ||||||
| 
 |  | ||||||
|     void drop_event(GUI::DropEvent&) override; |  | ||||||
| 
 |  | ||||||
|     void update_position(const int position); |  | ||||||
|     void update_ui(); |  | ||||||
|     int normalize_rate(int) const; |  | ||||||
|     int denormalize_rate(int) const; |  | ||||||
| 
 |  | ||||||
|     GUI::Window& m_window; |  | ||||||
| 
 |  | ||||||
|     float m_sample_ratio { 1.0 }; |  | ||||||
|     RefPtr<GUI::Label> m_status; |  | ||||||
|     RefPtr<GUI::Label> m_elapsed; |  | ||||||
|     RefPtr<GUI::Label> m_remaining; |  | ||||||
|     RefPtr<Slider> m_slider; |  | ||||||
|     RefPtr<SampleWidget> m_sample_widget; |  | ||||||
|     RefPtr<Gfx::Bitmap> m_play_icon { Gfx::Bitmap::load_from_file("/res/icons/16x16/play.png") }; |  | ||||||
|     RefPtr<Gfx::Bitmap> m_pause_icon { Gfx::Bitmap::load_from_file("/res/icons/16x16/pause.png") }; |  | ||||||
|     RefPtr<GUI::Button> m_play; |  | ||||||
|     RefPtr<GUI::Button> m_stop; |  | ||||||
| }; |  | ||||||
|  | @ -37,6 +37,7 @@ | ||||||
| #include <LibGUI/Label.h> | #include <LibGUI/Label.h> | ||||||
| #include <LibGUI/MessageBox.h> | #include <LibGUI/MessageBox.h> | ||||||
| #include <LibGUI/Slider.h> | #include <LibGUI/Slider.h> | ||||||
|  | #include <LibGUI/Splitter.h> | ||||||
| #include <LibGUI/ToolBar.h> | #include <LibGUI/ToolBar.h> | ||||||
| #include <LibGUI/ToolBarContainer.h> | #include <LibGUI/ToolBarContainer.h> | ||||||
| #include <LibGUI/Window.h> | #include <LibGUI/Window.h> | ||||||
|  | @ -212,10 +213,14 @@ void SoundPlayerWidgetAdvancedView::open_file(StringView path) | ||||||
|     m_playback_progress_slider->set_max(loader->total_samples()); |     m_playback_progress_slider->set_max(loader->total_samples()); | ||||||
|     m_playback_progress_slider->set_enabled(true); |     m_playback_progress_slider->set_enabled(true); | ||||||
|     m_play_button->set_enabled(true); |     m_play_button->set_enabled(true); | ||||||
|  |     m_play_button->set_icon(*m_pause_icon); | ||||||
|     m_stop_button->set_enabled(true); |     m_stop_button->set_enabled(true); | ||||||
|  |     m_playback_progress_slider->set_max(loader->total_samples()); | ||||||
|     manager().set_loader(move(loader)); |     manager().set_loader(move(loader)); | ||||||
|     set_has_loaded_file(true); |     set_has_loaded_file(true); | ||||||
|  |     set_loaded_file_samplerate(loader->sample_rate()); | ||||||
|     set_loaded_filename(path); |     set_loaded_filename(path); | ||||||
|  |     play(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void SoundPlayerWidgetAdvancedView::set_nonlinear_volume_slider(bool nonlinear) | void SoundPlayerWidgetAdvancedView::set_nonlinear_volume_slider(bool nonlinear) | ||||||
|  |  | ||||||
|  | @ -27,11 +27,12 @@ | ||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
| #include "BarsVisualizationWidget.h" | #include "BarsVisualizationWidget.h" | ||||||
|  | #include "Common.h" | ||||||
| #include "PlaybackManager.h" | #include "PlaybackManager.h" | ||||||
| #include "Player.h" | #include "Player.h" | ||||||
| #include "SoundPlayerWidget.h" |  | ||||||
| #include <AK/NonnullRefPtr.h> | #include <AK/NonnullRefPtr.h> | ||||||
| #include <LibAudio/ClientConnection.h> | #include <LibAudio/ClientConnection.h> | ||||||
|  | #include <LibGUI/Splitter.h> | ||||||
| #include <LibGUI/Widget.h> | #include <LibGUI/Widget.h> | ||||||
| 
 | 
 | ||||||
| class SoundPlayerWidgetAdvancedView final : public GUI::Widget | class SoundPlayerWidgetAdvancedView final : public GUI::Widget | ||||||
|  | @ -45,6 +46,9 @@ public: | ||||||
|     void open_file(StringView path) override; |     void open_file(StringView path) override; | ||||||
|     void read_playlist(StringView path); |     void read_playlist(StringView path); | ||||||
|     void play() override; |     void play() override; | ||||||
|  |     void set_nonlinear_volume_slider(bool nonlinear); | ||||||
|  |     void set_playlist_visible(bool visible); | ||||||
|  |     void try_fill_missing_info(Vector<M3UEntry>& entries, StringView playlist_p); | ||||||
| 
 | 
 | ||||||
|     template<typename T> |     template<typename T> | ||||||
|     void set_visualization() |     void set_visualization() | ||||||
|  | @ -52,12 +56,10 @@ public: | ||||||
|         m_visualization->remove_from_parent(); |         m_visualization->remove_from_parent(); | ||||||
|         update(); |         update(); | ||||||
|         auto new_visualization = T::construct(); |         auto new_visualization = T::construct(); | ||||||
|         insert_child_before(new_visualization, *static_cast<Core::Object*>(m_playback_progress_slider.ptr())); |         m_player_view->insert_child_before(new_visualization, *static_cast<Core::Object*>(m_playback_progress_slider.ptr())); | ||||||
|         m_visualization = new_visualization; |         m_visualization = new_visualization; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     void set_nonlinear_volume_slider(bool nonlinear); |  | ||||||
| 
 |  | ||||||
| private: | private: | ||||||
|     void drop_event(GUI::DropEvent& event) override; |     void drop_event(GUI::DropEvent& event) override; | ||||||
|     GUI::Window& m_window; |     GUI::Window& m_window; | ||||||
|  | @ -77,7 +79,7 @@ private: | ||||||
|     RefPtr<GUI::Button> m_stop_button; |     RefPtr<GUI::Button> m_stop_button; | ||||||
|     RefPtr<GUI::Button> m_back_button; |     RefPtr<GUI::Button> m_back_button; | ||||||
|     RefPtr<GUI::Button> m_next_button; |     RefPtr<GUI::Button> m_next_button; | ||||||
|     RefPtr<Slider> m_playback_progress_slider; |     RefPtr<AutoSlider> m_playback_progress_slider; | ||||||
|     RefPtr<GUI::Label> m_volume_label; |     RefPtr<GUI::Label> m_volume_label; | ||||||
| 
 | 
 | ||||||
|     bool m_nonlinear_volume_slider; |     bool m_nonlinear_volume_slider; | ||||||
|  |  | ||||||
|  | @ -31,4 +31,5 @@ | ||||||
| class Visualization { | class Visualization { | ||||||
| public: | public: | ||||||
|     virtual void set_buffer(RefPtr<Audio::Buffer> buffer) = 0; |     virtual void set_buffer(RefPtr<Audio::Buffer> buffer) = 0; | ||||||
|  |     virtual void set_samplerate(int) { } | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | @ -26,7 +26,7 @@ | ||||||
| 
 | 
 | ||||||
| #include "NoVisualizationWidget.h" | #include "NoVisualizationWidget.h" | ||||||
| #include "Player.h" | #include "Player.h" | ||||||
| #include "SoundPlayerWidget.h" | #include "SampleWidget.h" | ||||||
| #include "SoundPlayerWidgetAdvancedView.h" | #include "SoundPlayerWidgetAdvancedView.h" | ||||||
| #include <LibAudio/ClientConnection.h> | #include <LibAudio/ClientConnection.h> | ||||||
| #include <LibGUI/Action.h> | #include <LibGUI/Action.h> | ||||||
|  | @ -54,21 +54,24 @@ int main(int argc, char** argv) | ||||||
| 
 | 
 | ||||||
|     auto audio_client = Audio::ClientConnection::construct(); |     auto audio_client = Audio::ClientConnection::construct(); | ||||||
|     audio_client->handshake(); |     audio_client->handshake(); | ||||||
|     PlaybackManager playback_manager(audio_client); |  | ||||||
|     PlayerState initial_player_state { true, |  | ||||||
|         true, |  | ||||||
|         false, |  | ||||||
|         false, |  | ||||||
|         1.0, |  | ||||||
|         audio_client, |  | ||||||
|         playback_manager, |  | ||||||
|         "" }; |  | ||||||
| 
 | 
 | ||||||
|     if (pledge("stdio recvfd sendfd accept rpath thread", nullptr) < 0) { |     if (pledge("stdio recvfd sendfd accept rpath thread", nullptr) < 0) { | ||||||
|         perror("pledge"); |         perror("pledge"); | ||||||
|         return 1; |         return 1; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     PlaybackManager playback_manager(audio_client); | ||||||
|  |     PlayerState initial_player_state { true, | ||||||
|  |         true, | ||||||
|  |         false, | ||||||
|  |         false, | ||||||
|  |         false, | ||||||
|  |         44100, | ||||||
|  |         1.0, | ||||||
|  |         audio_client, | ||||||
|  |         playback_manager, | ||||||
|  |         "" }; | ||||||
|  | 
 | ||||||
|     auto app_icon = GUI::Icon::default_icon("app-sound-player"); |     auto app_icon = GUI::Icon::default_icon("app-sound-player"); | ||||||
| 
 | 
 | ||||||
|     auto window = GUI::Window::construct(); |     auto window = GUI::Window::construct(); | ||||||
|  | @ -78,12 +81,14 @@ int main(int argc, char** argv) | ||||||
|     auto menubar = GUI::MenuBar::construct(); |     auto menubar = GUI::MenuBar::construct(); | ||||||
| 
 | 
 | ||||||
|     auto& app_menu = menubar->add_menu("File"); |     auto& app_menu = menubar->add_menu("File"); | ||||||
|     // start in simple view by default
 | 
 | ||||||
|     Player* player = &window->set_main_widget<SoundPlayerWidget>(window, initial_player_state); |     auto& playlist_menu = menubar->add_menu("Playlist"); | ||||||
|     if (argc > 1) { | 
 | ||||||
|     String path = argv[1]; |     String path = argv[1]; | ||||||
|  |     // start in advanced view by default
 | ||||||
|  |     Player* player = &window->set_main_widget<SoundPlayerWidgetAdvancedView>(window, initial_player_state); | ||||||
|  |     if (argc > 1) { | ||||||
|         player->open_file(path); |         player->open_file(path); | ||||||
|         player->play(); |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     app_menu.add_action(GUI::CommonActions::make_open_action([&](auto&) { |     app_menu.add_action(GUI::CommonActions::make_open_action([&](auto&) { | ||||||
|  | @ -119,7 +124,7 @@ int main(int argc, char** argv) | ||||||
|     auto& playback_menu = menubar->add_menu("Playback"); |     auto& playback_menu = menubar->add_menu("Playback"); | ||||||
| 
 | 
 | ||||||
|     auto loop = GUI::Action::create_checkable("Loop", { Mod_Ctrl, Key_R }, [&](auto& action) { |     auto loop = GUI::Action::create_checkable("Loop", { Mod_Ctrl, Key_R }, [&](auto& action) { | ||||||
|         player->set_looping(action.is_checked()); |         player->set_looping_file(action.is_checked()); | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     playback_menu.add_action(move(loop)); |     playback_menu.add_action(move(loop)); | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Cesar Torres
						Cesar Torres