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(); 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(m_seek_slider->max()); + auto duration = m_playback_manager->duration().to_milliseconds(); + Time timestamp = Time::from_milliseconds(static_cast(round(progress * static_cast(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(); m_toolbar = toolbar_container.add(); @@ -56,7 +67,7 @@ VideoPlayerWidget::VideoPlayerWidget(GUI::Window& window) m_toolbar->add_action(*m_play_pause_action); m_toolbar->add(); m_timestamp_label = m_toolbar->add(); - m_timestamp_label->set_fixed_width(50); + m_timestamp_label->set_autosize(true); m_toolbar->add(); // 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(min(m_playback_manager->duration().to_milliseconds(), NumericLimits::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(timestamp.to_milliseconds()) / static_cast(m_playback_manager->duration().to_milliseconds()); + m_seek_slider->set_value(static_cast(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(); diff --git a/Userland/Libraries/LibVideo/Containers/Demuxer.h b/Userland/Libraries/LibVideo/Containers/Demuxer.h index 3ed163b7f3..dacc121678 100644 --- a/Userland/Libraries/LibVideo/Containers/Demuxer.h +++ b/Userland/Libraries/LibVideo/Containers/Demuxer.h @@ -28,7 +28,7 @@ public: return sample.release_nonnull(); } - virtual DecoderErrorOr seek_to_most_recent_keyframe(Track track, size_t timestamp) = 0; + virtual DecoderErrorOr seek_to_most_recent_keyframe(Track track, Time timestamp) = 0; virtual DecoderErrorOr