Skip to content

Commit

Permalink
Auto merge of #22449 - georgeroman:implement_htmlmediaelement_playbac…
Browse files Browse the repository at this point in the history
…k_rates, r=ferjm

Implement HTMLMediaElement defaultPlaybackRate and playbackRate

<!-- Please describe your changes on the following line: -->

---
<!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `___` with appropriate data: -->
- [X] `./mach build -d` does not report any errors
- [X] `./mach test-tidy` does not report any errors
- [X] These changes fix #22293

<!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.-->

<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/22449)
<!-- Reviewable:end -->
  • Loading branch information
bors-servo committed Dec 28, 2018
2 parents f80c497 + 9aea7fb commit ec846e3
Show file tree
Hide file tree
Showing 8 changed files with 128 additions and 57 deletions.
10 changes: 5 additions & 5 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions components/atoms/static_atoms.txt
Expand Up @@ -67,6 +67,7 @@ print
progress
radio
range
ratechange
readystatechange
reftest-wait
rejectionhandled
Expand Down
109 changes: 102 additions & 7 deletions components/script/dom/htmlmediaelement.rs
Expand Up @@ -164,6 +164,10 @@ pub struct HTMLMediaElement {
error: MutNullableDom<MediaError>,
/// <https://html.spec.whatwg.org/multipage/#dom-media-paused>
paused: Cell<bool>,
/// <https://html.spec.whatwg.org/multipage/#dom-media-defaultplaybackrate>
defaultPlaybackRate: Cell<f64>,
/// <https://html.spec.whatwg.org/multipage/#dom-media-playbackrate>
playbackRate: Cell<f64>,
/// <https://html.spec.whatwg.org/multipage/#attr-media-autoplay>
autoplaying: Cell<bool>,
/// <https://html.spec.whatwg.org/multipage/#delaying-the-load-event-flag>
Expand Down Expand Up @@ -235,6 +239,8 @@ impl HTMLMediaElement {
fired_loadeddata_event: Cell::new(false),
error: Default::default(),
paused: Cell::new(true),
defaultPlaybackRate: Cell::new(1.0),
playbackRate: Cell::new(1.0),
// FIXME(nox): Why is this initialised to true?
autoplaying: Cell::new(true),
delaying_the_load_event_flag: Default::default(),
Expand Down Expand Up @@ -271,6 +277,15 @@ impl HTMLMediaElement {
}
}

fn play_media(&self) {
if let Err(e) = self.player.set_rate(self.playbackRate.get()) {
warn!("Could not set the playback rate {:?}", e);
}
if let Err(e) = self.player.play() {
warn!("Could not play media {:?}", e);
}
}

/// Marks that element as delaying the load event or not.
///
/// Nothing happens if the element was already delaying the load event and
Expand Down Expand Up @@ -358,9 +373,7 @@ impl HTMLMediaElement {
}

this.fulfill_in_flight_play_promises(|| {
if let Err(e) = this.player.play() {
eprintln!("Could not play media {:?}", e);
}
this.play_media();
});
}),
window.upcast(),
Expand Down Expand Up @@ -449,9 +462,7 @@ impl HTMLMediaElement {
this.fulfill_in_flight_play_promises(|| {
// Step 2.1.
this.upcast::<EventTarget>().fire_event(atom!("playing"));
if let Err(e) = this.player.play() {
eprintln!("Could not play media {:?}", e);
}
this.play_media();

// Step 2.2.
// Done after running this closure in
Expand Down Expand Up @@ -888,6 +899,43 @@ impl HTMLMediaElement {
);
}

fn queue_ratechange_event(&self) {
let window = window_from_node(self);
let task_source = window.task_manager().media_element_task_source();
task_source.queue_simple_event(self.upcast(), atom!("ratechange"), &window);
}

// https://html.spec.whatwg.org/multipage/#potentially-playing
fn is_potentially_playing(&self) -> bool {
!self.paused.get() &&
// FIXME: We need https://github.com/servo/servo/pull/22348
// to know whether playback has ended or not
// !self.Ended() &&
self.error.get().is_none() &&
!self.is_blocked_media_element()
}

// https://html.spec.whatwg.org/multipage/#blocked-media-element
fn is_blocked_media_element(&self) -> bool {
self.ready_state.get() <= ReadyState::HaveCurrentData ||
self.is_paused_for_user_interaction() ||
self.is_paused_for_in_band_content()
}

// https://html.spec.whatwg.org/multipage/#paused-for-user-interaction
fn is_paused_for_user_interaction(&self) -> bool {
// FIXME: we will likely be able to fill this placeholder once (if) we
// implement the MediaSession API.
false
}

// https://html.spec.whatwg.org/multipage/#paused-for-in-band-content
fn is_paused_for_in_band_content(&self) -> bool {
// FIXME: we will likely be able to fill this placeholder once (if) we
// implement https://github.com/servo/servo/issues/22314
false
}

// https://html.spec.whatwg.org/multipage/#media-element-load-algorithm
fn media_element_load_algorithm(&self) {
// Reset the flag that signals whether loadeddata was ever fired for
Expand Down Expand Up @@ -960,7 +1008,7 @@ impl HTMLMediaElement {
}

// Step 7.
// FIXME(nox): Set playbackRate to defaultPlaybackRate.
self.playbackRate.set(self.defaultPlaybackRate.get());

// Step 8.
self.error.set(None);
Expand Down Expand Up @@ -1350,6 +1398,53 @@ impl HTMLMediaElementMethods for HTMLMediaElement {
self.paused.get()
}

/// https://html.spec.whatwg.org/multipage/#dom-media-defaultplaybackrate
fn GetDefaultPlaybackRate(&self) -> Fallible<Finite<f64>> {
Ok(Finite::wrap(self.defaultPlaybackRate.get()))
}

/// https://html.spec.whatwg.org/multipage/#dom-media-defaultplaybackrate
fn SetDefaultPlaybackRate(&self, value: Finite<f64>) -> ErrorResult {
let min_allowed = -64.0;
let max_allowed = 64.0;
if *value < min_allowed || *value > max_allowed {
return Err(Error::NotSupported);
}

if *value != self.defaultPlaybackRate.get() {
self.defaultPlaybackRate.set(*value);
self.queue_ratechange_event();
}

Ok(())
}

/// https://html.spec.whatwg.org/multipage/#dom-media-playbackrate
fn GetPlaybackRate(&self) -> Fallible<Finite<f64>> {
Ok(Finite::wrap(self.playbackRate.get()))
}

/// https://html.spec.whatwg.org/multipage/#dom-media-playbackrate
fn SetPlaybackRate(&self, value: Finite<f64>) -> ErrorResult {
let min_allowed = -64.0;
let max_allowed = 64.0;
if *value < min_allowed || *value > max_allowed {
return Err(Error::NotSupported);
}

if *value != self.playbackRate.get() {
self.playbackRate.set(*value);
self.queue_ratechange_event();
if self.is_potentially_playing() {
if let Err(e) = self.player.set_rate(*value) {
warn!("Could not set the playback rate {:?}", e);
}
}
}

Ok(())
}

// https://html.spec.whatwg.org/multipage/#dom-media-duration
fn Duration(&self) -> f64 {
self.duration.get()
Expand Down
4 changes: 2 additions & 2 deletions components/script/dom/webidls/HTMLMediaElement.webidl
Expand Up @@ -42,8 +42,8 @@ interface HTMLMediaElement : HTMLElement {
readonly attribute unrestricted double duration;
// Date getStartDate();
readonly attribute boolean paused;
// attribute double defaultPlaybackRate;
// attribute double playbackRate;
[Throws] attribute double defaultPlaybackRate;
[Throws] attribute double playbackRate;
readonly attribute TimeRanges played;
// readonly attribute TimeRanges seekable;
// readonly attribute boolean ended;
Expand Down
32 changes: 16 additions & 16 deletions tests/wpt/metadata/html/dom/interfaces.https.html.ini
Expand Up @@ -1041,10 +1041,10 @@
expected: FAIL

[HTMLMediaElement interface: document.createElement("video") must inherit property "defaultPlaybackRate" with the proper type]
expected: FAIL
expected: PASS

[HTMLMediaElement interface: document.createElement("video") must inherit property "playbackRate" with the proper type]
expected: FAIL
expected: PASS

[HTMLMediaElement interface: document.createElement("video") must inherit property "played" with the proper type]
expected: FAIL
Expand Down Expand Up @@ -1113,10 +1113,10 @@
expected: FAIL

[HTMLMediaElement interface: document.createElement("audio") must inherit property "defaultPlaybackRate" with the proper type]
expected: FAIL
expected: PASS

[HTMLMediaElement interface: document.createElement("audio") must inherit property "playbackRate" with the proper type]
expected: FAIL
expected: PASS

[HTMLMediaElement interface: document.createElement("audio") must inherit property "played" with the proper type]
expected: FAIL
Expand Down Expand Up @@ -1248,10 +1248,10 @@
expected: FAIL

[HTMLMediaElement interface: new Audio() must inherit property "defaultPlaybackRate" with the proper type]
expected: FAIL
expected: PASS

[HTMLMediaElement interface: new Audio() must inherit property "playbackRate" with the proper type]
expected: FAIL
expected: PASS

[HTMLMediaElement interface: new Audio() must inherit property "played" with the proper type]
expected: FAIL
Expand Down Expand Up @@ -1401,10 +1401,10 @@
expected: FAIL

[HTMLMediaElement interface: attribute defaultPlaybackRate]
expected: FAIL
expected: PASS

[HTMLMediaElement interface: attribute playbackRate]
expected: FAIL
expected: PASS

[HTMLMediaElement interface: attribute played]
expected: FAIL
Expand Down Expand Up @@ -6775,10 +6775,10 @@
expected: FAIL

[HTMLMediaElement interface: document.createElement("video") must inherit property "defaultPlaybackRate" with the proper type]
expected: FAIL
expected: PASS

[HTMLMediaElement interface: document.createElement("video") must inherit property "playbackRate" with the proper type]
expected: FAIL
expected: PASS

[HTMLMediaElement interface: document.createElement("video") must inherit property "seekable" with the proper type]
expected: FAIL
Expand Down Expand Up @@ -6820,10 +6820,10 @@
expected: FAIL

[HTMLMediaElement interface: document.createElement("audio") must inherit property "defaultPlaybackRate" with the proper type]
expected: FAIL
expected: PASS

[HTMLMediaElement interface: document.createElement("audio") must inherit property "playbackRate" with the proper type]
expected: FAIL
expected: PASS

[HTMLMediaElement interface: document.createElement("audio") must inherit property "seekable" with the proper type]
expected: FAIL
Expand Down Expand Up @@ -6865,10 +6865,10 @@
expected: FAIL

[HTMLMediaElement interface: new Audio() must inherit property "defaultPlaybackRate" with the proper type]
expected: FAIL
expected: PASS

[HTMLMediaElement interface: new Audio() must inherit property "playbackRate" with the proper type]
expected: FAIL
expected: PASS

[HTMLMediaElement interface: new Audio() must inherit property "seekable" with the proper type]
expected: FAIL
Expand Down Expand Up @@ -6985,10 +6985,10 @@
expected: FAIL

[HTMLMediaElement interface: attribute defaultPlaybackRate]
expected: FAIL
expected: PASS

[HTMLMediaElement interface: attribute playbackRate]
expected: FAIL
expected: PASS

[HTMLMediaElement interface: attribute seekable]
expected: FAIL
Expand Down
@@ -1,5 +1,6 @@
[event_timeupdate.html]
type: testharness
disabled: Until https://github.com/servo/servo/pull/22477 is merged
expected: TIMEOUT
[setting src attribute on a sufficiently long autoplay audio should trigger timeupdate event]
expected: NOTRUN
Expand Down
@@ -1,5 +1,6 @@
[event_timeupdate_noautoplay.html]
type: testharness
disabled: Until https://github.com/servo/servo/pull/22477 is merged
expected: TIMEOUT
[calling play() on a sufficiently long audio should trigger timeupdate event]
expected: NOTRUN
Expand Down

This file was deleted.

0 comments on commit ec846e3

Please sign in to comment.