summaryrefslogtreecommitdiff
path: root/Userland/Applications/VideoPlayer
diff options
context:
space:
mode:
authorZaggy1024 <zaggy1024@gmail.com>2022-11-11 22:26:19 -0600
committerAndreas Kling <kling@serenityos.org>2022-11-25 23:28:39 +0100
commitf31621b3f20b94f319390ac8fc786ee7f42d64d0 (patch)
treefcb566e7005432152121bd015f7ba92c4188ac07 /Userland/Applications/VideoPlayer
parente216d1a65f5a41060a38940525d8272a04db6f01 (diff)
downloadserenity-f31621b3f20b94f319390ac8fc786ee7f42d64d0.zip
VideoPlayer/LibVideo: Implement the UI functionality for seeking
With these changes, the seek bar can be used, but only to seek to the start of the file. Seeking to anywhere else in the file will cause an error in the demuxer. The timestamp label that was previously invisible now has its text set according to either the playback or seek slider's position.
Diffstat (limited to 'Userland/Applications/VideoPlayer')
-rw-r--r--Userland/Applications/VideoPlayer/VideoPlayerWidget.cpp59
-rw-r--r--Userland/Applications/VideoPlayer/VideoPlayerWidget.h3
2 files changed, 58 insertions, 4 deletions
diff --git a/Userland/Applications/VideoPlayer/VideoPlayerWidget.cpp b/Userland/Applications/VideoPlayer/VideoPlayerWidget.cpp
index f4d53ca8c4..bafc0f523a 100644
--- a/Userland/Applications/VideoPlayer/VideoPlayerWidget.cpp
+++ b/Userland/Applications/VideoPlayer/VideoPlayerWidget.cpp
@@ -38,6 +38,17 @@ VideoPlayerWidget::VideoPlayerWidget(GUI::Window& window)
m_seek_slider = player_controls_widget.add<GUI::HorizontalSlider>();
m_seek_slider->set_fixed_height(20);
m_seek_slider->set_enabled(false);
+ m_seek_slider->on_change = [&](int value) {
+ if (!m_playback_manager)
+ return;
+ update_seek_slider_max();
+ auto progress = value / static_cast<double>(m_seek_slider->max());
+ auto duration = m_playback_manager->duration().to_milliseconds();
+ Time timestamp = Time::from_milliseconds(static_cast<i64>(round(progress * static_cast<double>(duration))));
+ set_current_timestamp(timestamp);
+ m_playback_manager->seek_to_timestamp(timestamp);
+ };
+ m_seek_slider->set_jump_to_cursor(true);
auto& toolbar_container = player_controls_widget.add<GUI::ToolbarContainer>();
m_toolbar = toolbar_container.add<GUI::Toolbar>();
@@ -56,7 +67,7 @@ VideoPlayerWidget::VideoPlayerWidget(GUI::Window& window)
m_toolbar->add_action(*m_play_pause_action);
m_toolbar->add<GUI::VerticalSeparator>();
m_timestamp_label = m_toolbar->add<GUI::Label>();
- m_timestamp_label->set_fixed_width(50);
+ m_timestamp_label->set_autosize(true);
m_toolbar->add<GUI::Widget>(); // Filler widget
@@ -89,6 +100,7 @@ void VideoPlayerWidget::open_file(StringView filename)
close_file();
m_playback_manager = load_file_result.release_value();
+ update_seek_slider_max();
resume_playback();
}
@@ -162,6 +174,46 @@ void VideoPlayerWidget::on_decoding_error(Video::DecoderError const& error)
GUI::MessageBox::show(&m_window, String::formatted(text_format, error.string_literal()), "Video Player encountered an error"sv);
}
+void VideoPlayerWidget::update_seek_slider_max()
+{
+ if (!m_playback_manager) {
+ m_seek_slider->set_enabled(false);
+ return;
+ }
+
+ m_seek_slider->set_max(static_cast<int>(min(m_playback_manager->duration().to_milliseconds(), NumericLimits<int>::max())));
+ m_seek_slider->set_enabled(true);
+}
+
+void VideoPlayerWidget::set_current_timestamp(Time timestamp)
+{
+ set_time_label(timestamp);
+ if (!m_playback_manager)
+ return;
+ auto progress = static_cast<double>(timestamp.to_milliseconds()) / static_cast<double>(m_playback_manager->duration().to_milliseconds());
+ m_seek_slider->set_value(static_cast<int>(round(progress * m_seek_slider->max())), GUI::AllowCallback::No);
+}
+
+void VideoPlayerWidget::set_time_label(Time timestamp)
+{
+ StringBuilder string_builder;
+ auto append_time = [&](Time time) {
+ auto seconds = time.to_seconds();
+ string_builder.appendff("{:02}:{:02}:{:02}", seconds / 3600, seconds / 60, seconds % 60);
+ };
+
+ append_time(timestamp);
+
+ if (m_playback_manager) {
+ string_builder.append(" / "sv);
+ append_time(m_playback_manager->duration());
+ } else {
+ string_builder.append(" / --:--:--.---"sv);
+ }
+
+ m_timestamp_label->set_text(string_builder.string_view());
+}
+
void VideoPlayerWidget::event(Core::Event& event)
{
if (event.type() == Video::EventType::DecoderErrorOccurred) {
@@ -174,9 +226,8 @@ void VideoPlayerWidget::event(Core::Event& event)
m_video_display->set_bitmap(frame_event.frame());
m_video_display->repaint();
- m_seek_slider->set_max(m_playback_manager->duration().to_milliseconds());
- m_seek_slider->set_value(m_playback_manager->current_playback_time().to_milliseconds());
- m_seek_slider->set_enabled(true);
+ update_seek_slider_max();
+ set_current_timestamp(m_playback_manager->current_playback_time());
frame_event.accept();
} else if (event.type() == Video::EventType::PlaybackStatusChange) {
diff --git a/Userland/Applications/VideoPlayer/VideoPlayerWidget.h b/Userland/Applications/VideoPlayer/VideoPlayerWidget.h
index 9f3abe1ddc..2ef81d5251 100644
--- a/Userland/Applications/VideoPlayer/VideoPlayerWidget.h
+++ b/Userland/Applications/VideoPlayer/VideoPlayerWidget.h
@@ -36,6 +36,9 @@ private:
VideoPlayerWidget(GUI::Window&);
void update_play_pause_icon();
+ void update_seek_slider_max();
+ void set_current_timestamp(Time);
+ void set_time_label(Time);
void on_decoding_error(Video::DecoderError const&);
void display_next_frame();