mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-05-30 06:52:52 +00:00
AudioPlayer: Further decouple the player from the GUI
This commit is contained in:
parent
f9e4bff487
commit
e4d6a56a28
Notes:
sideshowbarker
2024-07-18 21:02:45 +09:00
Author: https://github.com/ngc6302h
Commit: e4d6a56a28
Pull-request: https://github.com/SerenityOS/serenity/pull/5878
Reviewed-by: https://github.com/Dexesttp
Reviewed-by: https://github.com/RealKC
Reviewed-by: https://github.com/alimpfard
6 changed files with 136 additions and 76 deletions
|
@ -28,11 +28,48 @@
|
||||||
|
|
||||||
#include "PlaybackManager.h"
|
#include "PlaybackManager.h"
|
||||||
#include "VisualizationBase.h"
|
#include "VisualizationBase.h"
|
||||||
|
#include <AK/RefPtr.h>
|
||||||
|
|
||||||
|
struct PlayerState {
|
||||||
|
bool is_paused;
|
||||||
|
bool is_stopped;
|
||||||
|
bool has_loaded_file;
|
||||||
|
bool is_looping;
|
||||||
|
double volume;
|
||||||
|
Audio::ClientConnection& connection;
|
||||||
|
PlaybackManager& manager;
|
||||||
|
StringView loaded_filename;
|
||||||
|
};
|
||||||
|
|
||||||
class Player {
|
class Player {
|
||||||
public:
|
public:
|
||||||
explicit Player() = default;
|
explicit Player(PlayerState& state)
|
||||||
|
: m_player_state(state) {};
|
||||||
virtual void open_file(StringView path) = 0;
|
virtual void open_file(StringView path) = 0;
|
||||||
virtual Audio::ClientConnection& client_connection() = 0;
|
virtual void play() = 0;
|
||||||
virtual PlaybackManager& playback_manager() = 0;
|
|
||||||
|
PlayerState& get_player_state() { return m_player_state; }
|
||||||
|
bool is_stopped() const { return m_player_state.is_stopped; }
|
||||||
|
bool is_paused() const { return m_player_state.is_paused; }
|
||||||
|
bool has_loaded_file() const { return m_player_state.has_loaded_file; }
|
||||||
|
double volume() const { return m_player_state.volume; }
|
||||||
|
bool looping() const { return m_player_state.is_looping; }
|
||||||
|
StringView& loaded_filename() { return m_player_state.loaded_filename; }
|
||||||
|
|
||||||
|
virtual void set_stopped(bool stopped) { m_player_state.is_stopped = stopped; }
|
||||||
|
virtual void set_paused(bool paused) { m_player_state.is_paused = paused; }
|
||||||
|
virtual void set_has_loaded_file(bool loaded) { m_player_state.has_loaded_file = loaded; }
|
||||||
|
virtual void set_volume(double volume) { m_player_state.volume = volume; }
|
||||||
|
virtual void set_looping(bool loop)
|
||||||
|
{
|
||||||
|
m_player_state.is_looping = loop;
|
||||||
|
manager().loop(loop);
|
||||||
|
}
|
||||||
|
virtual void set_loaded_filename(StringView& filename) { m_player_state.loaded_filename = filename; }
|
||||||
|
|
||||||
|
Audio::ClientConnection& client_connection() { return m_player_state.connection; }
|
||||||
|
PlaybackManager& manager() { return m_player_state.manager; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
PlayerState m_player_state;
|
||||||
};
|
};
|
||||||
|
|
|
@ -33,10 +33,9 @@
|
||||||
#include <LibGUI/Label.h>
|
#include <LibGUI/Label.h>
|
||||||
#include <LibGUI/MessageBox.h>
|
#include <LibGUI/MessageBox.h>
|
||||||
|
|
||||||
SoundPlayerWidget::SoundPlayerWidget(GUI::Window& window, Audio::ClientConnection& connection, PlaybackManager& manager)
|
SoundPlayerWidget::SoundPlayerWidget(GUI::Window& window, PlayerState& state)
|
||||||
: m_window(window)
|
: Player(state)
|
||||||
, m_connection(connection)
|
, m_window(window)
|
||||||
, m_manager(manager)
|
|
||||||
{
|
{
|
||||||
window.set_resizable(false);
|
window.set_resizable(false);
|
||||||
window.resize(350, 140);
|
window.resize(350, 140);
|
||||||
|
@ -68,8 +67,8 @@ SoundPlayerWidget::SoundPlayerWidget(GUI::Window& window, Audio::ClientConnectio
|
||||||
|
|
||||||
m_slider = add<Slider>(Orientation::Horizontal);
|
m_slider = add<Slider>(Orientation::Horizontal);
|
||||||
m_slider->set_min(0);
|
m_slider->set_min(0);
|
||||||
m_slider->set_enabled(false);
|
m_slider->set_enabled(has_loaded_file());
|
||||||
m_slider->on_knob_released = [&](int value) { m_manager.seek(denormalize_rate(value)); };
|
m_slider->on_knob_released = [&](int value) { manager().seek(denormalize_rate(value)); };
|
||||||
|
|
||||||
auto& control_widget = add<GUI::Widget>();
|
auto& control_widget = add<GUI::Widget>();
|
||||||
control_widget.set_fill_with_background_color(true);
|
control_widget.set_fill_with_background_color(true);
|
||||||
|
@ -79,16 +78,21 @@ SoundPlayerWidget::SoundPlayerWidget(GUI::Window& window, Audio::ClientConnectio
|
||||||
control_widget.layout()->set_spacing(10);
|
control_widget.layout()->set_spacing(10);
|
||||||
|
|
||||||
m_play = control_widget.add<GUI::Button>();
|
m_play = control_widget.add<GUI::Button>();
|
||||||
m_play->set_icon(*m_pause_icon);
|
m_play->set_icon(has_loaded_file() ? *m_play_icon : *m_pause_icon);
|
||||||
m_play->set_enabled(false);
|
m_play->set_enabled(has_loaded_file());
|
||||||
m_play->on_click = [this](auto) {
|
m_play->on_click = [this](auto) {
|
||||||
m_play->set_icon(m_manager.toggle_pause() ? *m_play_icon : *m_pause_icon);
|
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 = control_widget.add<GUI::Button>();
|
||||||
m_stop->set_enabled(false);
|
m_stop->set_enabled(has_loaded_file());
|
||||||
m_stop->set_icon(Gfx::Bitmap::load_from_file("/res/icons/16x16/stop.png"));
|
m_stop->set_icon(Gfx::Bitmap::load_from_file("/res/icons/16x16/stop.png"));
|
||||||
m_stop->on_click = [this](auto) { m_manager.stop(); };
|
m_stop->on_click = [this](auto) {
|
||||||
|
manager().stop();
|
||||||
|
set_stopped(true);
|
||||||
|
};
|
||||||
|
|
||||||
m_status = add<GUI::Label>();
|
m_status = add<GUI::Label>();
|
||||||
m_status->set_frame_shape(Gfx::FrameShape::Box);
|
m_status->set_frame_shape(Gfx::FrameShape::Box);
|
||||||
|
@ -96,11 +100,11 @@ SoundPlayerWidget::SoundPlayerWidget(GUI::Window& window, Audio::ClientConnectio
|
||||||
m_status->set_frame_thickness(4);
|
m_status->set_frame_thickness(4);
|
||||||
m_status->set_text_alignment(Gfx::TextAlignment::CenterLeft);
|
m_status->set_text_alignment(Gfx::TextAlignment::CenterLeft);
|
||||||
m_status->set_fixed_height(18);
|
m_status->set_fixed_height(18);
|
||||||
m_status->set_text("No file open!");
|
m_status->set_text(has_loaded_file() ? loaded_filename() : "No file open!");
|
||||||
|
|
||||||
update_position(0);
|
update_position(0);
|
||||||
|
|
||||||
m_manager.on_update = [&]() { update_ui(); };
|
manager().on_update = [&]() { update_ui(); };
|
||||||
}
|
}
|
||||||
|
|
||||||
SoundPlayerWidget::~SoundPlayerWidget()
|
SoundPlayerWidget::~SoundPlayerWidget()
|
||||||
|
@ -132,8 +136,10 @@ void SoundPlayerWidget::open_file(StringView path)
|
||||||
loader->num_channels(),
|
loader->num_channels(),
|
||||||
loader->bits_per_sample()));
|
loader->bits_per_sample()));
|
||||||
|
|
||||||
m_manager.set_loader(move(loader));
|
manager().set_loader(move(loader));
|
||||||
update_position(0);
|
update_position(0);
|
||||||
|
set_has_loaded_file(true);
|
||||||
|
set_loaded_filename(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SoundPlayerWidget::drop_event(GUI::DropEvent& event)
|
void SoundPlayerWidget::drop_event(GUI::DropEvent& event)
|
||||||
|
@ -161,16 +167,16 @@ int SoundPlayerWidget::denormalize_rate(int rate) const
|
||||||
|
|
||||||
void SoundPlayerWidget::update_ui()
|
void SoundPlayerWidget::update_ui()
|
||||||
{
|
{
|
||||||
m_sample_widget->set_buffer(m_manager.current_buffer());
|
m_sample_widget->set_buffer(manager().current_buffer());
|
||||||
m_play->set_icon(m_manager.is_paused() ? *m_play_icon : *m_pause_icon);
|
m_play->set_icon(manager().is_paused() ? *m_play_icon : *m_pause_icon);
|
||||||
update_position(m_manager.connection()->get_played_samples());
|
update_position(manager().connection()->get_played_samples());
|
||||||
}
|
}
|
||||||
|
|
||||||
void SoundPlayerWidget::update_position(const int position)
|
void SoundPlayerWidget::update_position(const int position)
|
||||||
{
|
{
|
||||||
int total_norm_samples = position + normalize_rate(m_manager.last_seek());
|
int total_norm_samples = position + normalize_rate(manager().last_seek());
|
||||||
float seconds = (total_norm_samples / static_cast<float>(PLAYBACK_MANAGER_RATE));
|
float seconds = (total_norm_samples / static_cast<float>(PLAYBACK_MANAGER_RATE));
|
||||||
float remaining_seconds = m_manager.total_length() - seconds;
|
float remaining_seconds = manager().total_length() - seconds;
|
||||||
|
|
||||||
m_elapsed->set_text(String::formatted(
|
m_elapsed->set_text(String::formatted(
|
||||||
"Elapsed:\n{}:{:02}.{:02}",
|
"Elapsed:\n{}:{:02}.{:02}",
|
||||||
|
@ -191,3 +197,10 @@ void SoundPlayerWidget::hide_scope(bool hide)
|
||||||
{
|
{
|
||||||
m_sample_widget->set_visible(!hide);
|
m_sample_widget->set_visible(!hide);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SoundPlayerWidget::play()
|
||||||
|
{
|
||||||
|
manager().play();
|
||||||
|
set_paused(false);
|
||||||
|
set_stopped(false);
|
||||||
|
}
|
||||||
|
|
|
@ -40,16 +40,15 @@ class SoundPlayerWidget final : public GUI::Widget
|
||||||
, public Player {
|
, public Player {
|
||||||
C_OBJECT(SoundPlayerWidget)
|
C_OBJECT(SoundPlayerWidget)
|
||||||
public:
|
public:
|
||||||
virtual ~SoundPlayerWidget() override;
|
~SoundPlayerWidget() override;
|
||||||
void open_file(StringView path) override;
|
void open_file(StringView path) override;
|
||||||
|
void play() override;
|
||||||
void hide_scope(bool);
|
void hide_scope(bool);
|
||||||
Audio::ClientConnection& client_connection() override { return m_connection; }
|
|
||||||
PlaybackManager& playback_manager() override { return m_manager; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
explicit SoundPlayerWidget(GUI::Window& window, Audio::ClientConnection& connection, PlaybackManager& manager);
|
explicit SoundPlayerWidget(GUI::Window& window, PlayerState& state);
|
||||||
|
|
||||||
virtual void drop_event(GUI::DropEvent&) override;
|
void drop_event(GUI::DropEvent&) override;
|
||||||
|
|
||||||
void update_position(const int position);
|
void update_position(const int position);
|
||||||
void update_ui();
|
void update_ui();
|
||||||
|
@ -57,8 +56,6 @@ private:
|
||||||
int denormalize_rate(int) const;
|
int denormalize_rate(int) const;
|
||||||
|
|
||||||
GUI::Window& m_window;
|
GUI::Window& m_window;
|
||||||
Audio::ClientConnection& m_connection;
|
|
||||||
PlaybackManager& m_manager;
|
|
||||||
|
|
||||||
float m_sample_ratio { 1.0 };
|
float m_sample_ratio { 1.0 };
|
||||||
RefPtr<GUI::Label> m_status;
|
RefPtr<GUI::Label> m_status;
|
||||||
|
|
|
@ -41,12 +41,10 @@
|
||||||
#include <LibGUI/Window.h>
|
#include <LibGUI/Window.h>
|
||||||
#include <LibGfx/Bitmap.h>
|
#include <LibGfx/Bitmap.h>
|
||||||
|
|
||||||
SoundPlayerWidgetAdvancedView::SoundPlayerWidgetAdvancedView(GUI::Window& window, Audio::ClientConnection& connection, PlaybackManager& manager)
|
SoundPlayerWidgetAdvancedView::SoundPlayerWidgetAdvancedView(GUI::Window& window, PlayerState& state)
|
||||||
: m_window(window)
|
: Player(state)
|
||||||
, m_connection(connection)
|
, m_window(window)
|
||||||
, m_manager(manager)
|
|
||||||
{
|
{
|
||||||
|
|
||||||
window.resize(455, 350);
|
window.resize(455, 350);
|
||||||
window.set_minimum_size(440, 130);
|
window.set_minimum_size(440, 130);
|
||||||
window.set_resizable(true);
|
window.set_resizable(true);
|
||||||
|
@ -65,9 +63,9 @@ SoundPlayerWidgetAdvancedView::SoundPlayerWidgetAdvancedView(GUI::Window& window
|
||||||
m_playback_progress_slider = add<Slider>(Orientation::Horizontal);
|
m_playback_progress_slider = add<Slider>(Orientation::Horizontal);
|
||||||
m_playback_progress_slider->set_fixed_height(20);
|
m_playback_progress_slider->set_fixed_height(20);
|
||||||
m_playback_progress_slider->set_min(0);
|
m_playback_progress_slider->set_min(0);
|
||||||
m_playback_progress_slider->set_max(m_manager.total_length() * 44100); //this value should be set when we load a new file
|
m_playback_progress_slider->set_max(this->manager().total_length() * 44100); //this value should be set when we load a new file
|
||||||
m_playback_progress_slider->on_knob_released = [&](int value) {
|
m_playback_progress_slider->on_knob_released = [&](int value) {
|
||||||
m_manager.seek(value);
|
this->manager().seek(value);
|
||||||
};
|
};
|
||||||
|
|
||||||
auto& toolbar_container = add<GUI::ToolBarContainer>();
|
auto& toolbar_container = add<GUI::ToolBarContainer>();
|
||||||
|
@ -75,20 +73,22 @@ SoundPlayerWidgetAdvancedView::SoundPlayerWidgetAdvancedView(GUI::Window& window
|
||||||
auto& menubar = toolbar_container.add<GUI::ToolBar>();
|
auto& menubar = toolbar_container.add<GUI::ToolBar>();
|
||||||
|
|
||||||
m_play_button = menubar.add<GUI::Button>();
|
m_play_button = menubar.add<GUI::Button>();
|
||||||
m_play_button->set_icon(*m_play_icon);
|
m_play_button->set_icon(is_paused() ? (!has_loaded_file() ? *m_play_icon : *m_pause_icon) : *m_pause_icon);
|
||||||
m_play_button->set_fixed_width(50);
|
m_play_button->set_fixed_width(50);
|
||||||
|
m_play_button->set_enabled(has_loaded_file());
|
||||||
m_play_button->on_click = [&](unsigned) {
|
m_play_button->on_click = [&](unsigned) {
|
||||||
bool paused = m_manager.toggle_pause();
|
bool paused = this->manager().toggle_pause();
|
||||||
|
set_paused(paused);
|
||||||
m_play_button->set_icon(paused ? *m_play_icon : *m_pause_icon);
|
m_play_button->set_icon(paused ? *m_play_icon : *m_pause_icon);
|
||||||
m_stop_button->set_enabled(!paused);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
m_stop_button = menubar.add<GUI::Button>();
|
m_stop_button = menubar.add<GUI::Button>();
|
||||||
m_stop_button->set_icon(*m_stop_icon);
|
m_stop_button->set_icon(*m_stop_icon);
|
||||||
m_stop_button->set_fixed_width(50);
|
m_stop_button->set_fixed_width(50);
|
||||||
|
m_stop_button->set_enabled(has_loaded_file());
|
||||||
m_stop_button->on_click = [&](unsigned) {
|
m_stop_button->on_click = [&](unsigned) {
|
||||||
m_manager.stop();
|
this->manager().stop();
|
||||||
|
set_stopped(true);
|
||||||
m_play_button->set_icon(*m_play_icon);
|
m_play_button->set_icon(*m_play_icon);
|
||||||
m_stop_button->set_enabled(false);
|
m_stop_button->set_enabled(false);
|
||||||
};
|
};
|
||||||
|
@ -100,13 +100,15 @@ SoundPlayerWidgetAdvancedView::SoundPlayerWidgetAdvancedView(GUI::Window& window
|
||||||
// filler_label
|
// filler_label
|
||||||
menubar.add<GUI::Label>();
|
menubar.add<GUI::Label>();
|
||||||
|
|
||||||
auto& back_button = menubar.add<GUI::Button>();
|
m_back_button = menubar.add<GUI::Button>();
|
||||||
back_button.set_fixed_width(50);
|
m_back_button->set_fixed_width(50);
|
||||||
back_button.set_icon(*m_back_icon);
|
m_back_button->set_icon(*m_back_icon);
|
||||||
|
m_back_button->set_enabled(has_loaded_file());
|
||||||
|
|
||||||
auto& next_button = menubar.add<GUI::Button>();
|
m_next_button = menubar.add<GUI::Button>();
|
||||||
next_button.set_fixed_width(50);
|
m_next_button->set_fixed_width(50);
|
||||||
next_button.set_icon(*m_next_icon);
|
m_next_button->set_icon(*m_next_icon);
|
||||||
|
m_next_button->set_enabled(has_loaded_file());
|
||||||
|
|
||||||
m_volume_label = &menubar.add<GUI::Label>();
|
m_volume_label = &menubar.add<GUI::Label>();
|
||||||
m_volume_label->set_fixed_width(30);
|
m_volume_label->set_fixed_width(30);
|
||||||
|
@ -127,41 +129,36 @@ SoundPlayerWidgetAdvancedView::SoundPlayerWidgetAdvancedView(GUI::Window& window
|
||||||
set_volume(1.);
|
set_volume(1.);
|
||||||
set_nonlinear_volume_slider(false);
|
set_nonlinear_volume_slider(false);
|
||||||
|
|
||||||
m_manager.on_update = [&]() {
|
manager().on_update = [&]() {
|
||||||
//TODO: make this program support other sample rates
|
//TODO: make this program support other sample rates
|
||||||
int samples_played = m_connection.get_played_samples() + m_manager.last_seek();
|
int samples_played = client_connection().get_played_samples() + this->manager().last_seek();
|
||||||
int current_second = samples_played / 44100;
|
int current_second = samples_played / 44100;
|
||||||
timestamp_label.set_text(String::formatted("Elapsed: {:02}:{:02}:{:02}", current_second / 3600, current_second / 60, current_second % 60));
|
timestamp_label.set_text(String::formatted("Elapsed: {:02}:{:02}:{:02}", current_second / 3600, current_second / 60, current_second % 60));
|
||||||
m_playback_progress_slider->set_value(samples_played);
|
m_playback_progress_slider->set_value(samples_played);
|
||||||
|
|
||||||
dynamic_cast<Visualization*>(m_visualization.ptr())->set_buffer(m_manager.current_buffer());
|
dynamic_cast<Visualization*>(m_visualization.ptr())->set_buffer(this->manager().current_buffer());
|
||||||
};
|
};
|
||||||
|
|
||||||
m_manager.on_load_sample_buffer = [&](Audio::Buffer& buffer) {
|
this->manager().on_load_sample_buffer = [&](Audio::Buffer& buffer) {
|
||||||
if (m_volume == 1.)
|
if (volume() == 1.)
|
||||||
return;
|
return;
|
||||||
auto sample_count = buffer.sample_count();
|
auto sample_count = buffer.sample_count();
|
||||||
if (sample_count % 4 == 0) {
|
if (sample_count % 4 == 0) {
|
||||||
const int total_iter = sample_count / (sizeof(AK::SIMD::f64x4) / sizeof(double) / 2);
|
const int total_iter = sample_count / (sizeof(AK::SIMD::f64x4) / sizeof(double) / 2);
|
||||||
AK::SIMD::f64x4* sample_ptr = const_cast<AK::SIMD::f64x4*>(reinterpret_cast<const AK::SIMD::f64x4*>((buffer.data())));
|
AK::SIMD::f64x4* sample_ptr = const_cast<AK::SIMD::f64x4*>(reinterpret_cast<const AK::SIMD::f64x4*>((buffer.data())));
|
||||||
for (int i = 0; i < total_iter; ++i) {
|
for (int i = 0; i < total_iter; ++i) {
|
||||||
sample_ptr[i] = sample_ptr[i] * m_volume;
|
sample_ptr[i] = sample_ptr[i] * volume();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const int total_iter = sample_count / (sizeof(AK::SIMD::f64x2) / sizeof(double) / 2);
|
const int total_iter = sample_count / (sizeof(AK::SIMD::f64x2) / sizeof(double) / 2);
|
||||||
AK::SIMD::f64x2* sample_ptr = const_cast<AK::SIMD::f64x2*>(reinterpret_cast<const AK::SIMD::f64x2*>((buffer.data())));
|
AK::SIMD::f64x2* sample_ptr = const_cast<AK::SIMD::f64x2*>(reinterpret_cast<const AK::SIMD::f64x2*>((buffer.data())));
|
||||||
for (int i = 0; i < total_iter; ++i) {
|
for (int i = 0; i < total_iter; ++i) {
|
||||||
sample_ptr[i] = sample_ptr[i] * m_volume;
|
sample_ptr[i] = sample_ptr[i] * volume();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
void SoundPlayerWidgetAdvancedView::set_volume(double value)
|
|
||||||
{
|
|
||||||
m_volume = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SoundPlayerWidgetAdvancedView::open_file(StringView path)
|
void SoundPlayerWidgetAdvancedView::open_file(StringView path)
|
||||||
{
|
{
|
||||||
NonnullRefPtr<Audio::Loader> loader = Audio::Loader::create(path);
|
NonnullRefPtr<Audio::Loader> loader = Audio::Loader::create(path);
|
||||||
|
@ -173,7 +170,12 @@ void SoundPlayerWidgetAdvancedView::open_file(StringView path)
|
||||||
}
|
}
|
||||||
m_window.set_title(String::formatted("{} - SoundPlayer", loader->file()->filename()));
|
m_window.set_title(String::formatted("{} - SoundPlayer", loader->file()->filename()));
|
||||||
m_playback_progress_slider->set_max(loader->total_samples());
|
m_playback_progress_slider->set_max(loader->total_samples());
|
||||||
m_manager.set_loader(move(loader));
|
m_playback_progress_slider->set_enabled(true);
|
||||||
|
m_play_button->set_enabled(true);
|
||||||
|
m_stop_button->set_enabled(true);
|
||||||
|
manager().set_loader(move(loader));
|
||||||
|
set_has_loaded_file(true);
|
||||||
|
set_loaded_filename(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SoundPlayerWidgetAdvancedView::set_nonlinear_volume_slider(bool nonlinear)
|
void SoundPlayerWidgetAdvancedView::set_nonlinear_volume_slider(bool nonlinear)
|
||||||
|
@ -196,5 +198,13 @@ void SoundPlayerWidgetAdvancedView::drop_event(GUI::DropEvent& event)
|
||||||
|
|
||||||
SoundPlayerWidgetAdvancedView::~SoundPlayerWidgetAdvancedView()
|
SoundPlayerWidgetAdvancedView::~SoundPlayerWidgetAdvancedView()
|
||||||
{
|
{
|
||||||
m_manager.on_load_sample_buffer = nullptr;
|
manager().on_load_sample_buffer = nullptr;
|
||||||
|
manager().on_update = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SoundPlayerWidgetAdvancedView::play()
|
||||||
|
{
|
||||||
|
manager().play();
|
||||||
|
set_paused(false);
|
||||||
|
set_stopped(false);
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,12 +39,11 @@ class SoundPlayerWidgetAdvancedView final : public GUI::Widget
|
||||||
C_OBJECT(SoundPlayerWidgetAdvancedView)
|
C_OBJECT(SoundPlayerWidgetAdvancedView)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit SoundPlayerWidgetAdvancedView(GUI::Window& window, Audio::ClientConnection& connection, PlaybackManager& manager);
|
explicit SoundPlayerWidgetAdvancedView(GUI::Window& window, PlayerState& state);
|
||||||
~SoundPlayerWidgetAdvancedView() override;
|
~SoundPlayerWidgetAdvancedView() override;
|
||||||
|
|
||||||
void open_file(StringView path) override;
|
void open_file(StringView path) override;
|
||||||
Audio::ClientConnection& client_connection() override { return m_connection; }
|
void play() override;
|
||||||
PlaybackManager& playback_manager() override { return m_manager; }
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void set_visualization()
|
void set_visualization()
|
||||||
|
@ -58,14 +57,9 @@ public:
|
||||||
|
|
||||||
void set_nonlinear_volume_slider(bool nonlinear);
|
void set_nonlinear_volume_slider(bool nonlinear);
|
||||||
|
|
||||||
void set_volume(double value);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void drop_event(GUI::DropEvent& event) override;
|
void drop_event(GUI::DropEvent& event) override;
|
||||||
|
|
||||||
GUI::Window& m_window;
|
GUI::Window& m_window;
|
||||||
Audio::ClientConnection& m_connection;
|
|
||||||
PlaybackManager& m_manager;
|
|
||||||
|
|
||||||
RefPtr<GUI::Widget> m_visualization;
|
RefPtr<GUI::Widget> m_visualization;
|
||||||
|
|
||||||
|
@ -77,9 +71,10 @@ private:
|
||||||
|
|
||||||
RefPtr<GUI::Button> m_play_button;
|
RefPtr<GUI::Button> m_play_button;
|
||||||
RefPtr<GUI::Button> m_stop_button;
|
RefPtr<GUI::Button> m_stop_button;
|
||||||
|
RefPtr<GUI::Button> m_back_button;
|
||||||
|
RefPtr<GUI::Button> m_next_button;
|
||||||
RefPtr<Slider> m_playback_progress_slider;
|
RefPtr<Slider> m_playback_progress_slider;
|
||||||
RefPtr<GUI::Label> m_volume_label;
|
RefPtr<GUI::Label> m_volume_label;
|
||||||
|
|
||||||
double m_volume;
|
|
||||||
bool m_nonlinear_volume_slider;
|
bool m_nonlinear_volume_slider;
|
||||||
};
|
};
|
||||||
|
|
|
@ -54,8 +54,15 @@ 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);
|
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");
|
||||||
|
@ -72,11 +79,11 @@ int main(int argc, char** argv)
|
||||||
|
|
||||||
auto& app_menu = menubar->add_menu("File");
|
auto& app_menu = menubar->add_menu("File");
|
||||||
// start in simple view by default
|
// start in simple view by default
|
||||||
Player* player = &window->set_main_widget<SoundPlayerWidget>(window, audio_client, playback_manager);
|
Player* player = &window->set_main_widget<SoundPlayerWidget>(window, initial_player_state);
|
||||||
if (argc > 1) {
|
if (argc > 1) {
|
||||||
String path = argv[1];
|
String path = argv[1];
|
||||||
player->open_file(path);
|
player->open_file(path);
|
||||||
player->playback_manager().play();
|
player->play();
|
||||||
}
|
}
|
||||||
|
|
||||||
app_menu.add_action(GUI::CommonActions::make_open_action([&](auto&) {
|
app_menu.add_action(GUI::CommonActions::make_open_action([&](auto&) {
|
||||||
|
@ -89,12 +96,13 @@ int main(int argc, char** argv)
|
||||||
RefPtr<GUI::Action> hide_scope;
|
RefPtr<GUI::Action> hide_scope;
|
||||||
|
|
||||||
auto advanced_view_check = GUI::Action::create_checkable("Advanced view", { Mod_Ctrl, Key_A }, [&](auto& action) {
|
auto advanced_view_check = GUI::Action::create_checkable("Advanced view", { Mod_Ctrl, Key_A }, [&](auto& action) {
|
||||||
|
PlayerState state = player->get_player_state();
|
||||||
window->close();
|
window->close();
|
||||||
if (action.is_checked()) {
|
if (action.is_checked()) {
|
||||||
player = &window->set_main_widget<SoundPlayerWidgetAdvancedView>(window, audio_client, playback_manager);
|
player = &window->set_main_widget<SoundPlayerWidgetAdvancedView>(window, state);
|
||||||
hide_scope->set_checkable(false);
|
hide_scope->set_checkable(false);
|
||||||
} else {
|
} else {
|
||||||
player = &window->set_main_widget<SoundPlayerWidget>(window, audio_client, playback_manager);
|
player = &window->set_main_widget<SoundPlayerWidget>(window, state);
|
||||||
hide_scope->set_checkable(true);
|
hide_scope->set_checkable(true);
|
||||||
}
|
}
|
||||||
window->show();
|
window->show();
|
||||||
|
@ -123,7 +131,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->playback_manager().loop(action.is_checked());
|
player->set_looping(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