mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 00:47:45 +00:00
Piano: Propagate errors in PlayerWidget
Co-authored-by: Sam Atkins <atkinssj@serenityos.org>
This commit is contained in:
parent
4311fd2774
commit
797a53b307
5 changed files with 80 additions and 46 deletions
|
@ -19,53 +19,67 @@
|
||||||
#include <LibGUI/Menu.h>
|
#include <LibGUI/Menu.h>
|
||||||
#include <LibGUI/TabWidget.h>
|
#include <LibGUI/TabWidget.h>
|
||||||
|
|
||||||
|
ErrorOr<NonnullRefPtr<MainWidget>> MainWidget::try_create(TrackManager& manager, AudioPlayerLoop& loop)
|
||||||
|
{
|
||||||
|
auto widget = TRY(adopt_nonnull_ref_or_enomem(new (nothrow) MainWidget(manager, loop)));
|
||||||
|
TRY(widget->initialize());
|
||||||
|
return widget;
|
||||||
|
}
|
||||||
|
|
||||||
MainWidget::MainWidget(TrackManager& track_manager, AudioPlayerLoop& loop)
|
MainWidget::MainWidget(TrackManager& track_manager, AudioPlayerLoop& loop)
|
||||||
: m_track_manager(track_manager)
|
: m_track_manager(track_manager)
|
||||||
, m_audio_loop(loop)
|
, m_audio_loop(loop)
|
||||||
{
|
{
|
||||||
set_layout<GUI::VerticalBoxLayout>();
|
}
|
||||||
|
|
||||||
|
ErrorOr<void> MainWidget::initialize()
|
||||||
|
{
|
||||||
|
(void)TRY(try_set_layout<GUI::VerticalBoxLayout>());
|
||||||
layout()->set_spacing(2);
|
layout()->set_spacing(2);
|
||||||
layout()->set_margins(2);
|
layout()->set_margins(2);
|
||||||
set_fill_with_background_color(true);
|
set_fill_with_background_color(true);
|
||||||
|
|
||||||
m_wave_widget = add<WaveWidget>(track_manager);
|
m_wave_widget = TRY(try_add<WaveWidget>(m_track_manager));
|
||||||
m_wave_widget->set_fixed_height(100);
|
m_wave_widget->set_fixed_height(100);
|
||||||
|
|
||||||
m_tab_widget = add<GUI::TabWidget>();
|
m_tab_widget = TRY(try_add<GUI::TabWidget>());
|
||||||
m_roll_widget = m_tab_widget->add_tab<RollWidget>("Piano Roll", track_manager);
|
m_roll_widget = TRY(m_tab_widget->try_add_tab<RollWidget>("Piano Roll", m_track_manager));
|
||||||
|
|
||||||
m_roll_widget->set_fixed_height(300);
|
m_roll_widget->set_fixed_height(300);
|
||||||
|
|
||||||
m_tab_widget->add_tab<SamplerWidget>("Sampler", track_manager);
|
(void)TRY(m_tab_widget->try_add_tab<SamplerWidget>("Sampler", m_track_manager));
|
||||||
|
m_player_widget = TRY(try_add<PlayerWidget>(m_track_manager, m_audio_loop));
|
||||||
|
|
||||||
m_player_widget = add<PlayerWidget>(track_manager, loop);
|
m_keys_and_knobs_container = TRY(try_add<GUI::Widget>());
|
||||||
|
(void)TRY(m_keys_and_knobs_container->try_set_layout<GUI::HorizontalBoxLayout>());
|
||||||
m_keys_and_knobs_container = add<GUI::Widget>();
|
|
||||||
m_keys_and_knobs_container->set_layout<GUI::HorizontalBoxLayout>();
|
|
||||||
m_keys_and_knobs_container->layout()->set_spacing(2);
|
m_keys_and_knobs_container->layout()->set_spacing(2);
|
||||||
m_keys_and_knobs_container->set_fixed_height(130);
|
m_keys_and_knobs_container->set_fixed_height(130);
|
||||||
m_keys_and_knobs_container->set_fill_with_background_color(true);
|
m_keys_and_knobs_container->set_fill_with_background_color(true);
|
||||||
|
|
||||||
m_keys_widget = m_keys_and_knobs_container->add<KeysWidget>(track_manager.keyboard());
|
m_keys_widget = TRY(m_keys_and_knobs_container->try_add<KeysWidget>(m_track_manager.keyboard()));
|
||||||
|
|
||||||
m_knobs_widget = m_keys_and_knobs_container->add<KnobsWidget>(track_manager, *this);
|
m_knobs_widget = TRY(m_keys_and_knobs_container->try_add<KnobsWidget>(m_track_manager, *this));
|
||||||
|
|
||||||
m_roll_widget->set_keys_widget(m_keys_widget);
|
m_roll_widget->set_keys_widget(m_keys_widget);
|
||||||
|
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWidget::add_track_actions(GUI::Menu& menu)
|
ErrorOr<void> MainWidget::add_track_actions(GUI::Menu& menu)
|
||||||
{
|
{
|
||||||
menu.add_action(GUI::Action::create("&Add Track", { Mod_Ctrl, Key_T }, Gfx::Bitmap::load_from_file("/res/icons/16x16/plus.png"sv).release_value_but_fixme_should_propagate_errors(), [&](auto&) {
|
TRY(menu.try_add_action(GUI::Action::create("&Add Track", { Mod_Ctrl, Key_T }, TRY(Gfx::Bitmap::load_from_file("/res/icons/16x16/plus.png"sv)), [&](auto&) {
|
||||||
m_player_widget->add_track();
|
m_player_widget->add_track();
|
||||||
}));
|
})));
|
||||||
|
|
||||||
menu.add_action(GUI::Action::create("&Next Track", { Mod_Ctrl, Key_N }, Gfx::Bitmap::load_from_file("/res/icons/16x16/go-last.png"sv).release_value_but_fixme_should_propagate_errors(), [&](auto&) {
|
TRY(menu.try_add_action(GUI::Action::create("&Next Track", { Mod_Ctrl, Key_N }, TRY(Gfx::Bitmap::load_from_file("/res/icons/16x16/go-last.png"sv)), [&](auto&) {
|
||||||
turn_off_pressed_keys();
|
turn_off_pressed_keys();
|
||||||
m_player_widget->next_track();
|
m_player_widget->next_track();
|
||||||
turn_on_pressed_keys();
|
turn_on_pressed_keys();
|
||||||
|
|
||||||
m_knobs_widget->update_knobs();
|
m_knobs_widget->update_knobs();
|
||||||
}));
|
})));
|
||||||
|
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: There are some unnecessary calls to update() throughout this program,
|
// FIXME: There are some unnecessary calls to update() throughout this program,
|
||||||
|
|
|
@ -23,11 +23,12 @@ class KnobsWidget;
|
||||||
class PlayerWidget;
|
class PlayerWidget;
|
||||||
|
|
||||||
class MainWidget final : public GUI::Widget {
|
class MainWidget final : public GUI::Widget {
|
||||||
C_OBJECT(MainWidget)
|
C_OBJECT_ABSTRACT(MainWidget)
|
||||||
public:
|
public:
|
||||||
|
static ErrorOr<NonnullRefPtr<MainWidget>> try_create(TrackManager&, AudioPlayerLoop&);
|
||||||
virtual ~MainWidget() override = default;
|
virtual ~MainWidget() override = default;
|
||||||
|
|
||||||
void add_track_actions(GUI::Menu&);
|
ErrorOr<void> add_track_actions(GUI::Menu&);
|
||||||
|
|
||||||
void set_octave_and_ensure_note_change(DSP::Keyboard::Direction);
|
void set_octave_and_ensure_note_change(DSP::Keyboard::Direction);
|
||||||
void set_octave_and_ensure_note_change(int);
|
void set_octave_and_ensure_note_change(int);
|
||||||
|
@ -35,6 +36,8 @@ public:
|
||||||
private:
|
private:
|
||||||
explicit MainWidget(TrackManager&, AudioPlayerLoop&);
|
explicit MainWidget(TrackManager&, AudioPlayerLoop&);
|
||||||
|
|
||||||
|
ErrorOr<void> initialize();
|
||||||
|
|
||||||
virtual void keydown_event(GUI::KeyEvent&) override;
|
virtual void keydown_event(GUI::KeyEvent&) override;
|
||||||
virtual void keyup_event(GUI::KeyEvent&) override;
|
virtual void keyup_event(GUI::KeyEvent&) override;
|
||||||
virtual void custom_event(Core::CustomEvent&) override;
|
virtual void custom_event(Core::CustomEvent&) override;
|
||||||
|
|
|
@ -16,25 +16,37 @@
|
||||||
#include <LibGUI/ItemListModel.h>
|
#include <LibGUI/ItemListModel.h>
|
||||||
#include <LibGUI/Label.h>
|
#include <LibGUI/Label.h>
|
||||||
|
|
||||||
|
ErrorOr<NonnullRefPtr<PlayerWidget>> PlayerWidget::create(TrackManager& manager, AudioPlayerLoop& loop)
|
||||||
|
{
|
||||||
|
auto widget = TRY(adopt_nonnull_ref_or_enomem(new (nothrow) PlayerWidget(manager, loop)));
|
||||||
|
|
||||||
|
widget->m_play_icon = TRY(Gfx::Bitmap::load_from_file("/res/icons/16x16/play.png"sv));
|
||||||
|
widget->m_pause_icon = TRY(Gfx::Bitmap::load_from_file("/res/icons/16x16/pause.png"sv));
|
||||||
|
widget->m_back_icon = TRY(Gfx::Bitmap::load_from_file("/res/icons/16x16/go-back.png"sv)); // Go back a note
|
||||||
|
widget->m_next_icon = TRY(Gfx::Bitmap::load_from_file("/res/icons/16x16/go-forward.png"sv)); // Advance a note
|
||||||
|
widget->m_add_track_icon = TRY(Gfx::Bitmap::load_from_file("/res/icons/16x16/plus.png"sv));
|
||||||
|
widget->m_next_track_icon = TRY(Gfx::Bitmap::load_from_file("/res/icons/16x16/go-last.png"sv));
|
||||||
|
TRY(widget->initialize());
|
||||||
|
|
||||||
|
return widget;
|
||||||
|
}
|
||||||
|
|
||||||
PlayerWidget::PlayerWidget(TrackManager& manager, AudioPlayerLoop& loop)
|
PlayerWidget::PlayerWidget(TrackManager& manager, AudioPlayerLoop& loop)
|
||||||
: m_track_manager(manager)
|
: m_track_manager(manager)
|
||||||
, m_audio_loop(loop)
|
, m_audio_loop(loop)
|
||||||
{
|
{
|
||||||
set_layout<GUI::HorizontalBoxLayout>();
|
}
|
||||||
|
|
||||||
|
ErrorOr<void> PlayerWidget::initialize()
|
||||||
|
{
|
||||||
|
(void)TRY(try_set_layout<GUI::HorizontalBoxLayout>());
|
||||||
set_fill_with_background_color(true);
|
set_fill_with_background_color(true);
|
||||||
m_track_number_choices.append("1");
|
TRY(m_track_number_choices.try_append("1"));
|
||||||
|
|
||||||
m_play_icon = Gfx::Bitmap::load_from_file("/res/icons/16x16/play.png"sv).release_value_but_fixme_should_propagate_errors();
|
RefPtr<GUI::Label> label = TRY(try_add<GUI::Label>("Track"));
|
||||||
m_pause_icon = Gfx::Bitmap::load_from_file("/res/icons/16x16/pause.png"sv).release_value_but_fixme_should_propagate_errors();
|
|
||||||
m_back_icon = Gfx::Bitmap::load_from_file("/res/icons/16x16/go-back.png"sv).release_value_but_fixme_should_propagate_errors(); // Go back a note
|
|
||||||
m_next_icon = Gfx::Bitmap::load_from_file("/res/icons/16x16/go-forward.png"sv).release_value_but_fixme_should_propagate_errors(); // Advance a note
|
|
||||||
m_add_track_icon = Gfx::Bitmap::load_from_file("/res/icons/16x16/plus.png"sv).release_value_but_fixme_should_propagate_errors();
|
|
||||||
m_next_track_icon = Gfx::Bitmap::load_from_file("/res/icons/16x16/go-last.png"sv).release_value_but_fixme_should_propagate_errors();
|
|
||||||
|
|
||||||
RefPtr<GUI::Label> label = add<GUI::Label>("Track");
|
|
||||||
label->set_max_width(75);
|
label->set_max_width(75);
|
||||||
|
|
||||||
m_track_dropdown = add<GUI::ComboBox>();
|
m_track_dropdown = TRY(try_add<GUI::ComboBox>());
|
||||||
m_track_dropdown->set_max_width(75);
|
m_track_dropdown->set_max_width(75);
|
||||||
m_track_dropdown->set_model(*GUI::ItemListModel<DeprecatedString>::create(m_track_number_choices));
|
m_track_dropdown->set_model(*GUI::ItemListModel<DeprecatedString>::create(m_track_number_choices));
|
||||||
m_track_dropdown->set_only_allow_values_from_model(true);
|
m_track_dropdown->set_only_allow_values_from_model(true);
|
||||||
|
@ -44,7 +56,7 @@ PlayerWidget::PlayerWidget(TrackManager& manager, AudioPlayerLoop& loop)
|
||||||
m_track_manager.set_current_track(model_index.row());
|
m_track_manager.set_current_track(model_index.row());
|
||||||
};
|
};
|
||||||
|
|
||||||
m_add_track_button = add<GUI::Button>();
|
m_add_track_button = TRY(try_add<GUI::Button>());
|
||||||
m_add_track_button->set_icon(*m_add_track_icon);
|
m_add_track_button->set_icon(*m_add_track_icon);
|
||||||
m_add_track_button->set_fixed_width(30);
|
m_add_track_button->set_fixed_width(30);
|
||||||
m_add_track_button->set_tooltip("Add Track");
|
m_add_track_button->set_tooltip("Add Track");
|
||||||
|
@ -53,7 +65,7 @@ PlayerWidget::PlayerWidget(TrackManager& manager, AudioPlayerLoop& loop)
|
||||||
add_track();
|
add_track();
|
||||||
};
|
};
|
||||||
|
|
||||||
m_next_track_button = add<GUI::Button>();
|
m_next_track_button = TRY(try_add<GUI::Button>());
|
||||||
m_next_track_button->set_icon(*m_next_track_icon);
|
m_next_track_button->set_icon(*m_next_track_icon);
|
||||||
m_next_track_button->set_fixed_width(30);
|
m_next_track_button->set_fixed_width(30);
|
||||||
m_next_track_button->set_tooltip("Next Track");
|
m_next_track_button->set_tooltip("Next Track");
|
||||||
|
@ -62,7 +74,7 @@ PlayerWidget::PlayerWidget(TrackManager& manager, AudioPlayerLoop& loop)
|
||||||
next_track();
|
next_track();
|
||||||
};
|
};
|
||||||
|
|
||||||
m_play_button = add<GUI::Button>();
|
m_play_button = TRY(try_add<GUI::Button>());
|
||||||
m_play_button->set_icon(*m_pause_icon);
|
m_play_button->set_icon(*m_pause_icon);
|
||||||
m_play_button->set_fixed_width(30);
|
m_play_button->set_fixed_width(30);
|
||||||
m_play_button->set_tooltip("Play/Pause playback");
|
m_play_button->set_tooltip("Play/Pause playback");
|
||||||
|
@ -77,7 +89,7 @@ PlayerWidget::PlayerWidget(TrackManager& manager, AudioPlayerLoop& loop)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
m_back_button = add<GUI::Button>();
|
m_back_button = TRY(try_add<GUI::Button>());
|
||||||
m_back_button->set_icon(*m_back_icon);
|
m_back_button->set_icon(*m_back_icon);
|
||||||
m_back_button->set_fixed_width(30);
|
m_back_button->set_fixed_width(30);
|
||||||
m_back_button->set_tooltip("Previous Note");
|
m_back_button->set_tooltip("Previous Note");
|
||||||
|
@ -86,7 +98,7 @@ PlayerWidget::PlayerWidget(TrackManager& manager, AudioPlayerLoop& loop)
|
||||||
m_track_manager.time_forward(-(sample_rate / (beats_per_minute / 60) / notes_per_beat));
|
m_track_manager.time_forward(-(sample_rate / (beats_per_minute / 60) / notes_per_beat));
|
||||||
};
|
};
|
||||||
|
|
||||||
m_next_button = add<GUI::Button>();
|
m_next_button = TRY(try_add<GUI::Button>());
|
||||||
m_next_button->set_icon(*m_next_icon);
|
m_next_button->set_icon(*m_next_icon);
|
||||||
m_next_button->set_fixed_width(30);
|
m_next_button->set_fixed_width(30);
|
||||||
m_next_button->set_tooltip("Next Note");
|
m_next_button->set_tooltip("Next Note");
|
||||||
|
@ -94,6 +106,8 @@ PlayerWidget::PlayerWidget(TrackManager& manager, AudioPlayerLoop& loop)
|
||||||
m_next_button->on_click = [this](unsigned) {
|
m_next_button->on_click = [this](unsigned) {
|
||||||
m_track_manager.time_forward((sample_rate / (beats_per_minute / 60) / notes_per_beat));
|
m_track_manager.time_forward((sample_rate / (beats_per_minute / 60) / notes_per_beat));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlayerWidget::add_track()
|
void PlayerWidget::add_track()
|
||||||
|
|
|
@ -15,6 +15,7 @@ class TrackManager;
|
||||||
class PlayerWidget final : public GUI::Toolbar {
|
class PlayerWidget final : public GUI::Toolbar {
|
||||||
C_OBJECT(PlayerWidget)
|
C_OBJECT(PlayerWidget)
|
||||||
public:
|
public:
|
||||||
|
static ErrorOr<NonnullRefPtr<PlayerWidget>> create(TrackManager&, AudioPlayerLoop&);
|
||||||
virtual ~PlayerWidget() override = default;
|
virtual ~PlayerWidget() override = default;
|
||||||
|
|
||||||
void add_track();
|
void add_track();
|
||||||
|
@ -24,6 +25,8 @@ public:
|
||||||
private:
|
private:
|
||||||
explicit PlayerWidget(TrackManager&, AudioPlayerLoop&);
|
explicit PlayerWidget(TrackManager&, AudioPlayerLoop&);
|
||||||
|
|
||||||
|
ErrorOr<void> initialize();
|
||||||
|
|
||||||
TrackManager& m_track_manager;
|
TrackManager& m_track_manager;
|
||||||
AudioPlayerLoop& m_audio_loop;
|
AudioPlayerLoop& m_audio_loop;
|
||||||
Vector<DeprecatedString> m_track_number_choices;
|
Vector<DeprecatedString> m_track_number_choices;
|
||||||
|
|
|
@ -41,7 +41,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
||||||
auto audio_loop = AudioPlayerLoop::construct(track_manager, need_to_write_wav, wav_writer);
|
auto audio_loop = AudioPlayerLoop::construct(track_manager, need_to_write_wav, wav_writer);
|
||||||
|
|
||||||
auto app_icon = GUI::Icon::default_icon("app-piano"sv);
|
auto app_icon = GUI::Icon::default_icon("app-piano"sv);
|
||||||
auto window = GUI::Window::construct();
|
auto window = TRY(GUI::Window::try_create());
|
||||||
auto main_widget = TRY(window->set_main_widget<MainWidget>(track_manager, audio_loop));
|
auto main_widget = TRY(window->set_main_widget<MainWidget>(track_manager, audio_loop));
|
||||||
window->set_title("Piano");
|
window->set_title("Piano");
|
||||||
window->resize(840, 600);
|
window->resize(840, 600);
|
||||||
|
@ -53,8 +53,8 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
||||||
}));
|
}));
|
||||||
main_widget_updater->start();
|
main_widget_updater->start();
|
||||||
|
|
||||||
auto& file_menu = window->add_menu("&File");
|
auto file_menu = TRY(window->try_add_menu("&File"));
|
||||||
file_menu.add_action(GUI::Action::create("Export", { Mod_Ctrl, Key_E }, TRY(Gfx::Bitmap::load_from_file("/res/icons/16x16/file-export.png"sv)), [&](const GUI::Action&) {
|
TRY(file_menu->try_add_action(GUI::Action::create("Export", { Mod_Ctrl, Key_E }, TRY(Gfx::Bitmap::load_from_file("/res/icons/16x16/file-export.png"sv)), [&](const GUI::Action&) {
|
||||||
save_path = GUI::FilePicker::get_save_filepath(window, "Untitled", "wav");
|
save_path = GUI::FilePicker::get_save_filepath(window, "Untitled", "wav");
|
||||||
if (!save_path.has_value())
|
if (!save_path.has_value())
|
||||||
return;
|
return;
|
||||||
|
@ -71,19 +71,19 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
need_to_write_wav = true;
|
need_to_write_wav = true;
|
||||||
}));
|
})));
|
||||||
file_menu.add_separator();
|
TRY(file_menu->try_add_separator());
|
||||||
file_menu.add_action(GUI::CommonActions::make_quit_action([](auto&) {
|
TRY(file_menu->try_add_action(GUI::CommonActions::make_quit_action([](auto&) {
|
||||||
GUI::Application::the()->quit();
|
GUI::Application::the()->quit();
|
||||||
return;
|
return;
|
||||||
}));
|
})));
|
||||||
|
|
||||||
auto& edit_menu = window->add_menu("&Edit");
|
auto edit_menu = TRY(window->try_add_menu("&Edit"));
|
||||||
main_widget->add_track_actions(edit_menu);
|
TRY(main_widget->add_track_actions(edit_menu));
|
||||||
|
|
||||||
auto& help_menu = window->add_menu("&Help");
|
auto help_menu = TRY(window->try_add_menu("&Help"));
|
||||||
help_menu.add_action(GUI::CommonActions::make_command_palette_action(window));
|
TRY(help_menu->try_add_action(GUI::CommonActions::make_command_palette_action(window)));
|
||||||
help_menu.add_action(GUI::CommonActions::make_about_action("Piano", app_icon, window));
|
TRY(help_menu->try_add_action(GUI::CommonActions::make_about_action("Piano", app_icon, window)));
|
||||||
|
|
||||||
window->show();
|
window->show();
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue