diff options
author | bors-servo <lbergstrom+bors@mozilla.com> | 2019-01-14 06:35:45 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-01-14 06:35:45 -0500 |
commit | 1f9b13479462d453f8e498f1caa192ae09961307 (patch) | |
tree | 0bcd0ae6a0f798e99ec08c1cb1f5755f52d82575 /components/script/dom/htmlmediaelement.rs | |
parent | 6197f1addad631455cb4dcb215e172896f54a9ab (diff) | |
parent | 352fed71d7359e93850a85750a2715dbd5c706b9 (diff) | |
download | servo-1f9b13479462d453f8e498f1caa192ae09961307.tar.gz servo-1f9b13479462d453f8e498f1caa192ae09961307.zip |
Auto merge of #22348 - germangb:html_media_ended, r=ferjm
Implement Ended media attribute
<!-- Please describe your changes on the following line: -->
This PR should implement:
* New method `HTMLMediaElement::earliest_possible_position()` for the [earliest possible position](https://html.spec.whatwg.org/multipage/media.html#earliest-possible-position)
* `Ended` attribute following https://html.spec.whatwg.org/multipage/media.html#ended-playback
* Queue steps for when the playback position reaches the end
This PR contains placeholders for the following issues (I can rebase changes after the corresponding PRs get merged)
- #22321 (Define the Loop attribute)
- #22293 (To identify playback direction. Either forwards or backwards)
---
<!-- 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 #22294.
<!-- 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/22348)
<!-- Reviewable:end -->
Diffstat (limited to 'components/script/dom/htmlmediaelement.rs')
-rw-r--r-- | components/script/dom/htmlmediaelement.rs | 103 |
1 files changed, 103 insertions, 0 deletions
diff --git a/components/script/dom/htmlmediaelement.rs b/components/script/dom/htmlmediaelement.rs index 64c36f1d017..dd83c2061de 100644 --- a/components/script/dom/htmlmediaelement.rs +++ b/components/script/dom/htmlmediaelement.rs @@ -1119,6 +1119,63 @@ impl HTMLMediaElement { // an unsupported format, or can otherwise not be rendered at all" if self.ready_state.get() < ReadyState::HaveMetadata { self.queue_dedicated_media_source_failure_steps(); + } else { + // https://html.spec.whatwg.org/multipage/#reaches-the-end + match self.direction_of_playback() { + PlaybackDirection::Forwards => { + // Step 1. + if self.Loop() { + self.seek( + self.earliest_possible_position(), + /* approximate_for_speed*/ false, + ); + } else { + // Step 2. + // The **ended playback** condition is implemented inside of + // the HTMLMediaElementMethods::Ended method + + // Step 3. + let window = window_from_node(self); + let this = Trusted::new(self); + + let _ = window.task_manager().media_element_task_source().queue( + task!(reaches_the_end_steps: move || { + let this = this.root(); + // Step 3.1. + this.upcast::<EventTarget>().fire_event(atom!("timeupdate")); + + // Step 3.2. + if this.Ended() && !this.Paused() { + // Step 3.2.1. + this.paused.set(true); + + // Step 3.2.2. + this.upcast::<EventTarget>().fire_event(atom!("pause")); + + // Step 3.2.3. + this.take_pending_play_promises(Err(Error::Abort)); + this.fulfill_in_flight_play_promises(|| ()); + } + + // Step 3.3. + this.upcast::<EventTarget>().fire_event(atom!("ended")); + }), + window.upcast(), + ); + } + }, + + PlaybackDirection::Backwards => { + if self.playback_position.get() <= self.earliest_possible_position() { + let window = window_from_node(self); + + window + .task_manager() + .media_element_task_source() + .queue_simple_event(self.upcast(), atom!("ended"), &window); + } + }, + } } }, PlayerEvent::Error => { @@ -1261,6 +1318,38 @@ impl HTMLMediaElement { }, } } + + // https://html.spec.whatwg.org/multipage/#earliest-possible-position + fn earliest_possible_position(&self) -> f64 { + self.played + .borrow() + .start(0) + .unwrap_or_else(|_| self.playback_position.get()) + } +} + +// XXX Placeholder for [https://github.com/servo/servo/issues/22293] +#[derive(Clone, Copy, JSTraceable, MallocSizeOf, PartialEq)] +enum PlaybackDirection { + Forwards, + #[allow(dead_code)] + Backwards, +} + +// XXX Placeholder implementations for: +// +// - https://github.com/servo/servo/issues/22293 +// - https://github.com/servo/servo/issues/22321 +impl HTMLMediaElement { + // https://github.com/servo/servo/issues/22293 + fn direction_of_playback(&self) -> PlaybackDirection { + PlaybackDirection::Forwards + } + + // https://github.com/servo/servo/pull/22321 + fn Loop(&self) -> bool { + false + } } impl HTMLMediaElementMethods for HTMLMediaElement { @@ -1514,6 +1603,20 @@ impl HTMLMediaElementMethods for HTMLMediaElement { self.seeking.get() } + // https://html.spec.whatwg.org/multipage/#ended-playback + fn Ended(&self) -> bool { + if self.ready_state.get() < ReadyState::HaveMetadata { + return false; + } + + let playback_pos = self.playback_position.get(); + + match self.direction_of_playback() { + PlaybackDirection::Forwards => playback_pos >= self.Duration() && !self.Loop(), + PlaybackDirection::Backwards => playback_pos <= self.earliest_possible_position(), + } + } + // https://html.spec.whatwg.org/multipage/#dom-media-fastseek fn FastSeek(&self, time: Finite<f64>) { self.seek(*time, /* approximate_for_speed */ true); |