LibWeb: Implement playbackRate

This commit is contained in:
Psychpsyo 2025-02-09 01:42:50 +01:00 committed by Sam Atkins
parent 986fe0f408
commit 14e354bc29
Notes: github-actions[bot] 2025-02-10 11:39:00 +00:00
5 changed files with 123 additions and 3 deletions

View file

@ -570,7 +570,8 @@ WebIDL::ExceptionOr<void> HTMLMediaElement::load_element()
set_duration(NAN);
}
// FIXME: 7. Set the playbackRate attribute to the value of the defaultPlaybackRate attribute.
// 7. Set the playbackRate attribute to the value of the defaultPlaybackRate attribute.
TRY(set_playback_rate(m_default_playback_rate));
// 8. Set the error attribute to null and the can autoplay flag to true.
m_error = nullptr;
@ -1650,6 +1651,48 @@ void HTMLMediaElement::set_paused(bool paused)
set_needs_style_update(true);
}
// https://html.spec.whatwg.org/multipage/media.html#dom-media-defaultplaybackrate
void HTMLMediaElement::set_default_playback_rate(double new_value)
{
// When the defaultPlaybackRate or playbackRate attributes change value (either by being set by script or by being changed directly by the user agent, e.g. in response to user
// control) the user agent must queue a media element task given the media element to fire an event named ratechange at the media element.
if (m_default_playback_rate != new_value) {
queue_a_media_element_task([this] {
dispatch_event(DOM::Event::create(realm(), HTML::EventNames::ratechange));
});
}
// on setting the attribute must be set to the new value.
m_default_playback_rate = new_value;
}
// https://html.spec.whatwg.org/multipage/media.html#dom-media-playbackrate
WebIDL::ExceptionOr<void> HTMLMediaElement::set_playback_rate(double new_value)
{
// on setting, the user agent must follow these steps:
// 1. If the given value is not supported by the user agent, then throw a "NotSupportedError" DOMException.
// FIXME: We need to support playback rates other than 1 for this to be even remotely useful.
if (new_value != 1.0)
return WebIDL::NotSupportedError::create(realm(), "Playback rates other than 1 are not supported."_string);
// When the defaultPlaybackRate or playbackRate attributes change value (either by being set by script or by being changed directly by the user agent, e.g. in response to user
// control) the user agent must queue a media element task given the media element to fire an event named ratechange at the media element.
if (m_playback_rate != new_value) {
queue_a_media_element_task([this] {
dispatch_event(DOM::Event::create(realm(), HTML::EventNames::ratechange));
});
}
// 2. Set playbackRate to the new value, and if the element is potentially playing, change the playback speed.
m_playback_rate = new_value;
if (potentially_playing()) {
// FIXME: Do this once playback speeds other than 1 are supported.
}
return {};
}
// https://html.spec.whatwg.org/multipage/media.html#blocked-media-element
bool HTMLMediaElement::blocked() const
{

View file

@ -109,6 +109,12 @@ public:
double volume() const { return m_volume; }
WebIDL::ExceptionOr<void> set_volume(double);
double default_playback_rate() const { return m_default_playback_rate; }
void set_default_playback_rate(double);
double playback_rate() const { return m_playback_rate; }
WebIDL::ExceptionOr<void> set_playback_rate(double);
bool muted() const { return m_muted; }
void set_muted(bool);
@ -266,6 +272,12 @@ private:
// 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-defaultplaybackrate
double m_default_playback_rate { 1.0 };
// https://html.spec.whatwg.org/multipage/media.html#dom-media-playbackrate
double m_playback_rate { 1.0 };
// https://html.spec.whatwg.org/multipage/media.html#dom-media-volume
double m_volume { 1.0 };

View file

@ -59,8 +59,8 @@ interface HTMLMediaElement : HTMLElement {
readonly attribute unrestricted double duration;
[FIXME] object getStartDate();
readonly attribute boolean paused;
[FIXME] attribute double defaultPlaybackRate;
[FIXME] attribute double playbackRate;
attribute double defaultPlaybackRate;
attribute double playbackRate;
[FIXME] attribute boolean preservesPitch;
[FIXME] readonly attribute TimeRanges played;
[FIXME] readonly attribute TimeRanges seekable;

View file

@ -0,0 +1,12 @@
Harness status: OK
Found 7 tests
7 Pass
Pass playbackRate initial value
Pass playbackRate set to small positive value
Pass playbackRate set to large positive value
Pass playbackRate set to small negative value
Pass playbackRate set to large negative value
Pass playbackRate set to 0
Pass playbackRate set to -1

View file

@ -0,0 +1,53 @@
<!doctype html>
<title>playbackRate</title>
<script src="../../../../../resources/testharness.js"></script>
<script src="../../../../../resources/testharnessreport.js"></script>
<div id=log></div>
<script>
test(function() {
var v = document.createElement('video');
assert_equals(v.playbackRate, 1);
}, 'playbackRate initial value');
function testPlaybackRateHelper(t, newPlaybackRate) {
var v = document.createElement('video');
var initialRate = v.playbackRate;
v.addEventListener('ratechange', t.step_func_done(function() {
assert_equals(v.playbackRate, newPlaybackRate);
}));
try {
v.playbackRate = newPlaybackRate;
} catch(e) {
assert_equals(e.name, 'NotSupportedError');
assert_equals(v.playbackRate, initialRate);
t.done();
}
}
async_test(function(t) {
testPlaybackRateHelper(this, 3);
}, "playbackRate set to small positive value");
async_test(function(t) {
testPlaybackRateHelper(this, 100);
}, "playbackRate set to large positive value");
async_test(function(t) {
testPlaybackRateHelper(this, -3);
}, "playbackRate set to small negative value");
async_test(function(t) {
testPlaybackRateHelper(this, -100);
}, "playbackRate set to large negative value");
async_test(function(t) {
testPlaybackRateHelper(this, 0);
}, "playbackRate set to 0");
async_test(function(t) {
testPlaybackRateHelper(this, -1);
}, "playbackRate set to -1");
</script>