mirror of
https://github.com/RGBCube/serenity
synced 2025-07-23 13:17:36 +00:00
LibWeb: Implement the HTMLMediaElement paused attribute
Note that the default value of the attribute is true. We were previously autoplaying videos as soon as they loaded - this will prevent that from happening until the paused attribute is set to false.
This commit is contained in:
parent
e130525c24
commit
90921a4f16
5 changed files with 68 additions and 7 deletions
|
@ -179,9 +179,14 @@ WebIDL::ExceptionOr<void> HTMLMediaElement::load_element()
|
||||||
if (m_ready_state != ReadyState::HaveNothing)
|
if (m_ready_state != ReadyState::HaveNothing)
|
||||||
set_ready_state(ReadyState::HaveNothing);
|
set_ready_state(ReadyState::HaveNothing);
|
||||||
|
|
||||||
// FIXME: 6. If the paused attribute is false, then:
|
// 6. If the paused attribute is false, then:
|
||||||
|
if (!paused()) {
|
||||||
// 1. Set the paused attribute to true.
|
// 1. Set the paused attribute to true.
|
||||||
// 2. Take pending play promises and reject pending play promises with the result and an "AbortError" DOMException.
|
set_paused(true);
|
||||||
|
|
||||||
|
// FIXME 2. Take pending play promises and reject pending play promises with the result and an "AbortError" DOMException.
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME: 7. If seeking is true, set it to false.
|
// FIXME: 7. If seeking is true, set it to false.
|
||||||
// FIXME: 8. Set the current playback position to 0.
|
// FIXME: 8. Set the current playback position to 0.
|
||||||
// Set the official playback position to 0.
|
// Set the official playback position to 0.
|
||||||
|
@ -737,7 +742,10 @@ void HTMLMediaElement::set_ready_state(ReadyState ready_state)
|
||||||
dispatch_event(DOM::Event::create(this->realm(), HTML::EventNames::canplay).release_value_but_fixme_should_propagate_errors());
|
dispatch_event(DOM::Event::create(this->realm(), HTML::EventNames::canplay).release_value_but_fixme_should_propagate_errors());
|
||||||
});
|
});
|
||||||
|
|
||||||
// FIXME: If the element's paused attribute is false, the user agent must notify about playing for the element.
|
// If the element's paused attribute is false, the user agent must notify about playing for the element.
|
||||||
|
if (!paused())
|
||||||
|
notify_about_playing();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -746,10 +754,12 @@ void HTMLMediaElement::set_ready_state(ReadyState ready_state)
|
||||||
// If the previous ready state was HAVE_CURRENT_DATA or less, the user agent must queue a media element task given the media element to fire an event
|
// If the previous ready state was HAVE_CURRENT_DATA or less, the user agent must queue a media element task given the media element to fire an event
|
||||||
// named canplay at the element, and, if the element's paused attribute is false, notify about playing for the element.
|
// named canplay at the element, and, if the element's paused attribute is false, notify about playing for the element.
|
||||||
if (m_ready_state <= ReadyState::HaveCurrentData) {
|
if (m_ready_state <= ReadyState::HaveCurrentData) {
|
||||||
// FIXME: Handle the paused attribute.
|
|
||||||
queue_a_media_element_task([this] {
|
queue_a_media_element_task([this] {
|
||||||
dispatch_event(DOM::Event::create(this->realm(), HTML::EventNames::canplay).release_value_but_fixme_should_propagate_errors());
|
dispatch_event(DOM::Event::create(this->realm(), HTML::EventNames::canplay).release_value_but_fixme_should_propagate_errors());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (!paused())
|
||||||
|
notify_about_playing();
|
||||||
}
|
}
|
||||||
|
|
||||||
// The user agent must queue a media element task given the media element to fire an event named canplaythrough at the element.
|
// The user agent must queue a media element task given the media element to fire an event named canplaythrough at the element.
|
||||||
|
@ -774,4 +784,31 @@ void HTMLMediaElement::set_ready_state(ReadyState ready_state)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://html.spec.whatwg.org/multipage/media.html#notify-about-playing
|
||||||
|
void HTMLMediaElement::notify_about_playing()
|
||||||
|
{
|
||||||
|
// FIXME: 1. Take pending play promises and let promises be the result.
|
||||||
|
|
||||||
|
// 2. Queue a media element task given the element and the following steps:
|
||||||
|
queue_a_media_element_task([this]() {
|
||||||
|
// 1. Fire an event named playing at the element.
|
||||||
|
dispatch_event(DOM::Event::create(realm(), HTML::EventNames::playing).release_value_but_fixme_should_propagate_errors());
|
||||||
|
|
||||||
|
// FIXME: 2. Resolve pending play promises with promises.
|
||||||
|
});
|
||||||
|
|
||||||
|
on_playing();
|
||||||
|
}
|
||||||
|
|
||||||
|
void HTMLMediaElement::set_paused(bool paused)
|
||||||
|
{
|
||||||
|
if (m_paused == paused)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_paused = paused;
|
||||||
|
|
||||||
|
if (m_paused)
|
||||||
|
on_paused();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,6 +45,7 @@ public:
|
||||||
|
|
||||||
WebIDL::ExceptionOr<void> load();
|
WebIDL::ExceptionOr<void> load();
|
||||||
double duration() const;
|
double duration() const;
|
||||||
|
bool paused() const { return m_paused; }
|
||||||
void pause() const;
|
void pause() const;
|
||||||
|
|
||||||
JS::NonnullGCPtr<VideoTrackList> video_tracks() const { return *m_video_tracks; }
|
JS::NonnullGCPtr<VideoTrackList> video_tracks() const { return *m_video_tracks; }
|
||||||
|
@ -55,6 +56,11 @@ protected:
|
||||||
virtual JS::ThrowCompletionOr<void> initialize(JS::Realm&) override;
|
virtual JS::ThrowCompletionOr<void> initialize(JS::Realm&) override;
|
||||||
virtual void visit_edges(Cell::Visitor&) override;
|
virtual void visit_edges(Cell::Visitor&) override;
|
||||||
|
|
||||||
|
// Override in subclasses to handle implementation-specific behavior when the element state changes
|
||||||
|
// to playing or paused, e.g. to start/stop play timers.
|
||||||
|
virtual void on_playing() { }
|
||||||
|
virtual void on_paused() { }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct EntireResource { };
|
struct EntireResource { };
|
||||||
using ByteRange = Variant<EntireResource>; // FIXME: This will need to include "until end" and an actual byte range.
|
using ByteRange = Variant<EntireResource>; // FIXME: This will need to include "until end" and an actual byte range.
|
||||||
|
@ -71,6 +77,9 @@ private:
|
||||||
WebIDL::ExceptionOr<void> handle_media_source_failure();
|
WebIDL::ExceptionOr<void> handle_media_source_failure();
|
||||||
void forget_media_resource_specific_tracks();
|
void forget_media_resource_specific_tracks();
|
||||||
void set_ready_state(ReadyState);
|
void set_ready_state(ReadyState);
|
||||||
|
|
||||||
|
void notify_about_playing();
|
||||||
|
void set_paused(bool);
|
||||||
void set_duration(double);
|
void set_duration(double);
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/media.html#media-element-event-task-source
|
// https://html.spec.whatwg.org/multipage/media.html#media-element-event-task-source
|
||||||
|
@ -86,6 +95,9 @@ private:
|
||||||
// https://html.spec.whatwg.org/multipage/media.html#dom-media-duration
|
// https://html.spec.whatwg.org/multipage/media.html#dom-media-duration
|
||||||
double m_duration { NAN };
|
double m_duration { NAN };
|
||||||
|
|
||||||
|
// https://html.spec.whatwg.org/multipage/media.html#dom-media-paused
|
||||||
|
bool m_paused { true };
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/media.html#dom-media-videotracks
|
// https://html.spec.whatwg.org/multipage/media.html#dom-media-videotracks
|
||||||
JS::GCPtr<VideoTrackList> m_video_tracks;
|
JS::GCPtr<VideoTrackList> m_video_tracks;
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,7 @@ interface HTMLMediaElement : HTMLElement {
|
||||||
|
|
||||||
// playback state
|
// playback state
|
||||||
readonly attribute unrestricted double duration;
|
readonly attribute unrestricted double duration;
|
||||||
|
readonly attribute boolean paused;
|
||||||
[Reflect, CEReactions] attribute boolean autoplay;
|
[Reflect, CEReactions] attribute boolean autoplay;
|
||||||
[Reflect, CEReactions] attribute boolean loop;
|
[Reflect, CEReactions] attribute boolean loop;
|
||||||
undefined pause();
|
undefined pause();
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2020, the SerenityOS developers.
|
* Copyright (c) 2020, the SerenityOS developers.
|
||||||
|
* Copyright (c) 2023, Tim Flynn <trflynn89@serenityos.org>
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
@ -84,9 +85,10 @@ void HTMLVideoElement::set_video_track(JS::GCPtr<HTML::VideoTrack> video_track)
|
||||||
m_video_timer->stop();
|
m_video_timer->stop();
|
||||||
|
|
||||||
m_video_track = video_track;
|
m_video_track = video_track;
|
||||||
if (!m_video_track)
|
}
|
||||||
return;
|
|
||||||
|
|
||||||
|
void HTMLVideoElement::on_playing()
|
||||||
|
{
|
||||||
if (!m_video_timer) {
|
if (!m_video_timer) {
|
||||||
m_video_timer = Platform::Timer::create_repeating(s_frame_delay_ms, [this]() {
|
m_video_timer = Platform::Timer::create_repeating(s_frame_delay_ms, [this]() {
|
||||||
if (auto frame = m_video_track->next_frame())
|
if (auto frame = m_video_track->next_frame())
|
||||||
|
@ -101,4 +103,10 @@ void HTMLVideoElement::set_video_track(JS::GCPtr<HTML::VideoTrack> video_track)
|
||||||
m_video_timer->start();
|
m_video_timer->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HTMLVideoElement::on_paused()
|
||||||
|
{
|
||||||
|
if (m_video_timer)
|
||||||
|
m_video_timer->stop();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,6 +38,9 @@ private:
|
||||||
|
|
||||||
virtual JS::GCPtr<Layout::Node> create_layout_node(NonnullRefPtr<CSS::StyleProperties>) override;
|
virtual JS::GCPtr<Layout::Node> create_layout_node(NonnullRefPtr<CSS::StyleProperties>) override;
|
||||||
|
|
||||||
|
virtual void on_playing() override;
|
||||||
|
virtual void on_paused() override;
|
||||||
|
|
||||||
JS::GCPtr<HTML::VideoTrack> m_video_track;
|
JS::GCPtr<HTML::VideoTrack> m_video_track;
|
||||||
RefPtr<Platform::Timer> m_video_timer;
|
RefPtr<Platform::Timer> m_video_timer;
|
||||||
RefPtr<Gfx::Bitmap> m_current_frame;
|
RefPtr<Gfx::Bitmap> m_current_frame;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue