diff options
author | Andreas Kling <kling@serenityos.org> | 2021-01-12 12:05:23 +0100 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-01-12 12:05:23 +0100 |
commit | dc28c07fa526841e05e16161c74a6c23984f1dd5 (patch) | |
tree | d68796bc7708eba33fbf7247e1a92188ac5acf6f /Applications/SoundPlayer | |
parent | aa939c4b4b8a7eb1d22b166ebb5fb737d6e66714 (diff) | |
download | serenity-dc28c07fa526841e05e16161c74a6c23984f1dd5.zip |
Applications: Move to Userland/Applications/
Diffstat (limited to 'Applications/SoundPlayer')
-rw-r--r-- | Applications/SoundPlayer/CMakeLists.txt | 9 | ||||
-rw-r--r-- | Applications/SoundPlayer/PlaybackManager.cpp | 188 | ||||
-rw-r--r-- | Applications/SoundPlayer/PlaybackManager.h | 77 | ||||
-rw-r--r-- | Applications/SoundPlayer/SampleWidget.cpp | 82 | ||||
-rw-r--r-- | Applications/SoundPlayer/SampleWidget.h | 47 | ||||
-rw-r--r-- | Applications/SoundPlayer/SoundPlayerWidget.cpp | 194 | ||||
-rw-r--r-- | Applications/SoundPlayer/SoundPlayerWidget.h | 94 | ||||
-rw-r--r-- | Applications/SoundPlayer/main.cpp | 109 |
8 files changed, 0 insertions, 800 deletions
diff --git a/Applications/SoundPlayer/CMakeLists.txt b/Applications/SoundPlayer/CMakeLists.txt deleted file mode 100644 index 99e1da4653..0000000000 --- a/Applications/SoundPlayer/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -set(SOURCES - main.cpp - PlaybackManager.cpp - SampleWidget.cpp - SoundPlayerWidget.cpp -) - -serenity_app(SoundPlayer ICON app-sound-player) -target_link_libraries(SoundPlayer LibAudio LibGUI) diff --git a/Applications/SoundPlayer/PlaybackManager.cpp b/Applications/SoundPlayer/PlaybackManager.cpp deleted file mode 100644 index 1421e75215..0000000000 --- a/Applications/SoundPlayer/PlaybackManager.cpp +++ /dev/null @@ -1,188 +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 "PlaybackManager.h" - -PlaybackManager::PlaybackManager(NonnullRefPtr<Audio::ClientConnection> connection) - : m_connection(connection) -{ - m_timer = Core::Timer::construct(100, [&]() { - if (!m_loader) - return; - next_buffer(); - }); - m_timer->stop(); -} - -PlaybackManager::~PlaybackManager() -{ -} - -void PlaybackManager::set_loader(NonnullRefPtr<Audio::Loader>&& loader) -{ - stop(); - m_loader = loader; - if (m_loader) { - m_total_length = m_loader->total_samples() / static_cast<float>(m_loader->sample_rate()); - m_timer->start(); - load_next_buffer(); - } else { - m_timer->stop(); - } -} - -void PlaybackManager::stop() -{ - set_paused(true); - m_connection->clear_buffer(true); - m_buffers.clear(); - m_last_seek = 0; - m_next_buffer = nullptr; - m_current_buffer = nullptr; - m_next_ptr = 0; - - if (m_loader) - m_loader->reset(); -} - -void PlaybackManager::play() -{ - set_paused(false); -} - -void PlaybackManager::loop(bool loop) -{ - m_loop = loop; -} - -void PlaybackManager::seek(const int position) -{ - if (!m_loader) - return; - - m_last_seek = position; - bool paused_state = m_paused; - set_paused(true); - - m_connection->clear_buffer(true); - m_next_buffer = nullptr; - m_current_buffer = nullptr; - m_next_ptr = 0; - m_buffers.clear(); - m_loader->seek(position); - - if (!paused_state) - set_paused(false); -} - -void PlaybackManager::pause() -{ - set_paused(true); -} - -void PlaybackManager::remove_dead_buffers() -{ - int id = m_connection->get_playing_buffer(); - int current_id = -1; - if (m_current_buffer) - current_id = m_current_buffer->shbuf_id(); - - if (id >= 0 && id != current_id) { - while (!m_buffers.is_empty()) { - --m_next_ptr; - auto buffer = m_buffers.take_first(); - - if (buffer->shbuf_id() == id) { - m_current_buffer = buffer; - break; - } - } - } -} - -void PlaybackManager::load_next_buffer() -{ - if (m_buffers.size() < 10) { - for (int i = 0; i < 20 && m_loader->loaded_samples() < m_loader->total_samples(); i++) { - auto buffer = m_loader->get_more_samples(PLAYBACK_MANAGER_BUFFER_SIZE); - if (buffer) - m_buffers.append(buffer); - } - } - - if (m_next_ptr < m_buffers.size()) { - m_next_buffer = m_buffers.at(m_next_ptr++); - } else { - m_next_buffer = nullptr; - } -} - -void PlaybackManager::set_paused(bool paused) -{ - if (!m_next_buffer && m_loader) - load_next_buffer(); - - m_paused = paused; - m_connection->set_paused(paused); -} - -bool PlaybackManager::toggle_pause() -{ - if (m_paused) { - play(); - } else { - pause(); - } - return m_paused; -} - -void PlaybackManager::next_buffer() -{ - if (on_update) - on_update(); - - if (m_paused) - return; - - remove_dead_buffers(); - if (!m_next_buffer) { - if (!m_connection->get_remaining_samples() && !m_paused) { - dbgln("Exhausted samples :^)"); - if (m_loop) - seek(0); - else - stop(); - } - - return; - } - - bool enqueued = m_connection->try_enqueue(*m_next_buffer); - if (!enqueued) - return; - - load_next_buffer(); -} diff --git a/Applications/SoundPlayer/PlaybackManager.h b/Applications/SoundPlayer/PlaybackManager.h deleted file mode 100644 index 35be78fe9d..0000000000 --- a/Applications/SoundPlayer/PlaybackManager.h +++ /dev/null @@ -1,77 +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 <AK/Vector.h> -#include <LibAudio/Buffer.h> -#include <LibAudio/ClientConnection.h> -#include <LibAudio/Loader.h> -#include <LibCore/Timer.h> - -#define PLAYBACK_MANAGER_BUFFER_SIZE 64 * KiB -#define PLAYBACK_MANAGER_RATE 44100 - -class PlaybackManager final { -public: - PlaybackManager(NonnullRefPtr<Audio::ClientConnection>); - ~PlaybackManager(); - - void play(); - void stop(); - void pause(); - void seek(const int position); - void loop(bool); - bool toggle_pause(); - void set_loader(NonnullRefPtr<Audio::Loader>&&); - - int last_seek() const { return m_last_seek; } - bool is_paused() const { return m_paused; } - float total_length() const { return m_total_length; } - RefPtr<Audio::Buffer> current_buffer() const { return m_current_buffer; } - - NonnullRefPtr<Audio::ClientConnection> connection() const { return m_connection; } - - Function<void()> on_update; - -private: - void next_buffer(); - void set_paused(bool); - void load_next_buffer(); - void remove_dead_buffers(); - - bool m_paused { true }; - bool m_loop = { false }; - size_t m_next_ptr { 0 }; - size_t m_last_seek { 0 }; - float m_total_length { 0 }; - RefPtr<Audio::Loader> m_loader { nullptr }; - NonnullRefPtr<Audio::ClientConnection> m_connection; - RefPtr<Audio::Buffer> m_next_buffer; - RefPtr<Audio::Buffer> m_current_buffer; - Vector<RefPtr<Audio::Buffer>> m_buffers; - RefPtr<Core::Timer> m_timer; -}; diff --git a/Applications/SoundPlayer/SampleWidget.cpp b/Applications/SoundPlayer/SampleWidget.cpp deleted file mode 100644 index b3884a175a..0000000000 --- a/Applications/SoundPlayer/SampleWidget.cpp +++ /dev/null @@ -1,82 +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 "SampleWidget.h" -#include <LibAudio/Buffer.h> -#include <LibGUI/Painter.h> -#include <math.h> - -SampleWidget::SampleWidget() -{ -} - -SampleWidget::~SampleWidget() -{ -} - -void SampleWidget::paint_event(GUI::PaintEvent& event) -{ - GUI::Frame::paint_event(event); - GUI::Painter painter(*this); - - painter.add_clip_rect(event.rect()); - painter.fill_rect(frame_inner_rect(), Color::Black); - - float sample_max = 0; - int count = 0; - int x_offset = frame_inner_rect().x(); - int x = x_offset; - int y_offset = frame_inner_rect().center().y(); - - if (m_buffer) { - int samples_per_pixel = m_buffer->sample_count() / frame_inner_rect().width(); - for (int sample_index = 0; sample_index < m_buffer->sample_count() && (x - x_offset) < frame_inner_rect().width(); ++sample_index) { - float sample = fabsf((float)m_buffer->samples()[sample_index].left); - - sample_max = max(sample, sample_max); - ++count; - - if (count >= samples_per_pixel) { - Gfx::IntPoint min_point = { x, y_offset + static_cast<int>(-sample_max * frame_inner_rect().height() / 2) }; - Gfx::IntPoint max_point = { x++, y_offset + static_cast<int>(sample_max * frame_inner_rect().height() / 2) }; - painter.draw_line(min_point, max_point, Color::Green); - - count = 0; - sample_max = 0; - } - } - } else { - painter.draw_line({ x, y_offset }, { frame_inner_rect().width(), y_offset }, Color::Green); - } -} - -void SampleWidget::set_buffer(Audio::Buffer* buffer) -{ - if (m_buffer == buffer) - return; - m_buffer = buffer; - update(); -} diff --git a/Applications/SoundPlayer/SampleWidget.h b/Applications/SoundPlayer/SampleWidget.h deleted file mode 100644 index 7da9c20b38..0000000000 --- a/Applications/SoundPlayer/SampleWidget.h +++ /dev/null @@ -1,47 +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 <LibGUI/Frame.h> - -namespace Audio { -class Buffer; -} - -class SampleWidget final : public GUI::Frame { - C_OBJECT(SampleWidget) -public: - virtual ~SampleWidget() override; - - void set_buffer(Audio::Buffer*); - -private: - SampleWidget(); - virtual void paint_event(GUI::PaintEvent&) override; - - RefPtr<Audio::Buffer> m_buffer; -}; diff --git a/Applications/SoundPlayer/SoundPlayerWidget.cpp b/Applications/SoundPlayer/SoundPlayerWidget.cpp deleted file mode 100644 index f2066aca89..0000000000 --- a/Applications/SoundPlayer/SoundPlayerWidget.cpp +++ /dev/null @@ -1,194 +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 <AK/StringBuilder.h> -#include <LibCore/MimeData.h> -#include <LibGUI/BoxLayout.h> -#include <LibGUI/Button.h> -#include <LibGUI/Label.h> -#include <LibGUI/MessageBox.h> -#include <math.h> - -SoundPlayerWidget::SoundPlayerWidget(GUI::Window& window, NonnullRefPtr<Audio::ClientConnection> connection) - : m_window(window) - , m_connection(connection) - , m_manager(connection) -{ - 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(false); - m_slider->on_knob_released = [&](int value) { m_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(*m_pause_icon); - m_play->set_enabled(false); - m_play->on_click = [this](auto) { - m_play->set_icon(m_manager.toggle_pause() ? *m_play_icon : *m_pause_icon); - }; - - m_stop = control_widget.add<GUI::Button>(); - m_stop->set_enabled(false); - m_stop->set_icon(Gfx::Bitmap::load_from_file("/res/icons/16x16/stop.png")); - m_stop->on_click = [this](auto) { m_manager.stop(); }; - - 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("No file open!"); - - update_position(0); - - m_manager.on_update = [&]() { update_ui(); }; -} - -SoundPlayerWidget::~SoundPlayerWidget() -{ -} - -SoundPlayerWidget::Slider::~Slider() -{ -} - -void SoundPlayerWidget::hide_scope(bool hide) -{ - m_sample_widget->set_visible(!hide); -} - -void SoundPlayerWidget::open_file(String 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())); - - m_manager.set_loader(move(loader)); - update_position(0); -} - -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(m_manager.current_buffer()); - m_play->set_icon(m_manager.is_paused() ? *m_play_icon : *m_pause_icon); - update_position(m_manager.connection()->get_played_samples()); -} - -void SoundPlayerWidget::update_position(const int position) -{ - int total_norm_samples = position + normalize_rate(m_manager.last_seek()); - float seconds = (total_norm_samples / static_cast<float>(PLAYBACK_MANAGER_RATE)); - float remaining_seconds = m_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); -} diff --git a/Applications/SoundPlayer/SoundPlayerWidget.h b/Applications/SoundPlayer/SoundPlayerWidget.h deleted file mode 100644 index ab7bc60aea..0000000000 --- a/Applications/SoundPlayer/SoundPlayerWidget.h +++ /dev/null @@ -1,94 +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 "PlaybackManager.h" -#include "SampleWidget.h" -#include <LibGUI/Button.h> -#include <LibGUI/Label.h> -#include <LibGUI/Slider.h> -#include <LibGUI/Widget.h> -#include <LibGUI/Window.h> - -class SoundPlayerWidget final : public GUI::Widget { - C_OBJECT(SoundPlayerWidget) -public: - virtual ~SoundPlayerWidget() override; - void open_file(String path); - void hide_scope(bool); - PlaybackManager& manager() { return m_manager; } - -private: - explicit SoundPlayerWidget(GUI::Window&, NonnullRefPtr<Audio::ClientConnection>); - - virtual 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; - - class Slider final : public GUI::Slider { - C_OBJECT(Slider) - public: - virtual ~Slider() override; - Function<void(int)> on_knob_released; - void set_value(int value) - { - if (!knob_dragging()) - GUI::Slider::set_value(value); - } - - protected: - Slider(Orientation orientation) - : GUI::Slider(orientation) - { - } - - virtual void mouseup_event(GUI::MouseEvent& event) override - { - if (on_knob_released && is_enabled()) - on_knob_released(value()); - - GUI::Slider::mouseup_event(event); - } - }; - - GUI::Window& m_window; - NonnullRefPtr<Audio::ClientConnection> m_connection; - PlaybackManager m_manager; - 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; -}; diff --git a/Applications/SoundPlayer/main.cpp b/Applications/SoundPlayer/main.cpp deleted file mode 100644 index 47dbd555c8..0000000000 --- a/Applications/SoundPlayer/main.cpp +++ /dev/null @@ -1,109 +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 <LibAudio/ClientConnection.h> -#include <LibGUI/Action.h> -#include <LibGUI/Application.h> -#include <LibGUI/FilePicker.h> -#include <LibGUI/Menu.h> -#include <LibGUI/MenuBar.h> -#include <LibGUI/Window.h> -#include <LibGfx/CharacterBitmap.h> -#include <stdio.h> - -int main(int argc, char** argv) -{ - if (pledge("stdio shared_buffer accept rpath thread unix cpath fattr", nullptr) < 0) { - perror("pledge"); - return 1; - } - - auto app = GUI::Application::construct(argc, argv); - - if (pledge("stdio shared_buffer accept rpath thread unix", nullptr) < 0) { - perror("pledge"); - return 1; - } - - auto audio_client = Audio::ClientConnection::construct(); - audio_client->handshake(); - - if (pledge("stdio shared_buffer accept rpath thread", nullptr) < 0) { - perror("pledge"); - return 1; - } - - auto app_icon = GUI::Icon::default_icon("app-sound-player"); - - auto window = GUI::Window::construct(); - window->set_title("Sound Player"); - window->set_resizable(false); - window->resize(350, 140); - window->set_icon(app_icon.bitmap_for_size(16)); - - auto menubar = GUI::MenuBar::construct(); - auto& app_menu = menubar->add_menu("Sound Player"); - auto& player = window->set_main_widget<SoundPlayerWidget>(window, audio_client); - - if (argc > 1) { - String path = argv[1]; - player.open_file(path); - player.manager().play(); - } - - auto hide_scope = GUI::Action::create_checkable("Hide scope", { Mod_Ctrl, Key_H }, [&](auto& action) { - player.hide_scope(action.is_checked()); - }); - - app_menu.add_action(GUI::CommonActions::make_open_action([&](auto&) { - Optional<String> path = GUI::FilePicker::get_open_filepath(window, "Open sound file..."); - if (path.has_value()) { - player.open_file(path.value()); - } - })); - app_menu.add_action(move(hide_scope)); - app_menu.add_separator(); - app_menu.add_action(GUI::CommonActions::make_quit_action([&](auto&) { - app->quit(); - })); - - auto& playback_menu = menubar->add_menu("Playback"); - - auto loop = GUI::Action::create_checkable("Loop", { Mod_Ctrl, Key_R }, [&](auto& action) { - player.manager().loop(action.is_checked()); - }); - - playback_menu.add_action(move(loop)); - - auto& help_menu = menubar->add_menu("Help"); - help_menu.add_action(GUI::CommonActions::make_about_action("Sound Player", app_icon, window)); - - app->set_menubar(move(menubar)); - - window->show(); - return app->exec(); -} |