Skip to content

Commit

Permalink
Auto merge of #22348 - germangb:html_media_ended, r=<try>
Browse files Browse the repository at this point in the history
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
- [ ] 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 -->
  • Loading branch information
bors-servo committed Dec 7, 2018
2 parents 3c19cd4 + 5db4e49 commit 81fd21e
Show file tree
Hide file tree
Showing 2 changed files with 104 additions and 1 deletion.
103 changes: 103 additions & 0 deletions components/script/dom/htmlmediaelement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1217,6 +1217,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::FrameUpdated => {
Expand Down Expand Up @@ -1245,6 +1302,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 {
Expand Down Expand Up @@ -1367,6 +1456,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, /* approximat_for_speed */ true);
Expand Down
2 changes: 1 addition & 1 deletion components/script/dom/webidls/HTMLMediaElement.webidl
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ interface HTMLMediaElement : HTMLElement {
// attribute double playbackRate;
readonly attribute TimeRanges played;
// readonly attribute TimeRanges seekable;
// readonly attribute boolean ended;
readonly attribute boolean ended;
[CEReactions] attribute boolean autoplay;
// [CEReactions] attribute boolean loop;
Promise<void> play();
Expand Down

0 comments on commit 81fd21e

Please sign in to comment.