Implement play, pause, paused, and autoplay APIs.

This commit is contained in:
Josh Matthews 2015-11-07 01:19:41 -05:00
parent 5960fbe604
commit e3db11fd8b
20 changed files with 118 additions and 399 deletions

View file

@ -162,6 +162,8 @@ pub struct HTMLMediaElement {
generation_id: Cell<u32>,
first_data_load: Cell<bool>,
error: MutNullableHeap<JS<MediaError>>,
paused: Cell<bool>,
autoplaying: Cell<bool>,
}
impl HTMLMediaElement {
@ -177,6 +179,8 @@ impl HTMLMediaElement {
generation_id: Cell::new(0),
first_data_load: Cell::new(true),
error: Default::default(),
paused: Cell::new(true),
autoplaying: Cell::new(true),
}
}
@ -185,6 +189,28 @@ impl HTMLMediaElement {
&self.htmlelement
}
// https://html.spec.whatwg.org/multipage/#playing-the-media-resource:internal-pause-steps
fn internal_pause_steps(&self) {
// Step 1
self.autoplaying.set(false);
// Step 2
if !self.Paused() {
// 2.1
self.paused.set(true);
// 2.2
self.queue_fire_simple_event("timeupdate");
// 2.3
self.queue_fire_simple_event("pause");
// TODO 2.4 (official playback position)
}
// TODO step 3 (media controller)
}
fn queue_fire_simple_event(&self, type_: &'static str) {
let win = window_from_node(self);
let task = FireSimpleEventTask::new(self, type_);
@ -260,11 +286,19 @@ impl HTMLMediaElement {
if old_ready_state <= HAVE_CURRENT_DATA {
self.queue_fire_simple_event("canplay");
//TODO: check paused state
self.queue_fire_simple_event("playing");
if !self.Paused() {
self.queue_fire_simple_event("playing");
}
}
// TODO: autoplay-related logic
if self.autoplaying.get() &&
self.Paused() &&
self.Autoplay() {
self.paused.set(false);
// TODO: show poster
self.queue_fire_simple_event("play");
self.queue_fire_simple_event("playing");
}
self.queue_fire_simple_event("canplaythrough");
}
@ -274,7 +308,7 @@ impl HTMLMediaElement {
}
// https://html.spec.whatwg.org/multipage/#concept-media-load-algorithm
fn invoke_resource_selection_algorithm(&self, base_url: Url) {
fn invoke_resource_selection_algorithm(&self) {
// Step 1
self.network_state.set(NETWORK_NO_SOURCE);
@ -282,7 +316,8 @@ impl HTMLMediaElement {
// TODO step 3 (delay load event)
// Step 4
ScriptThread::await_stable_state(ResourceSelectionTask::new(self, base_url));
let doc = document_from_node(self);
ScriptThread::await_stable_state(ResourceSelectionTask::new(self, doc.base_url()));
}
// https://html.spec.whatwg.org/multipage/#concept-media-load-algorithm
@ -434,7 +469,9 @@ impl HTMLMediaElement {
// 4.4
self.change_ready_state(HAVE_NOTHING);
// TODO 4.5 (paused)
if !self.Paused() {
self.paused.set(true);
}
// TODO 4.6 (seeking)
// TODO 4.7 (playback position)
// TODO 4.8 (timeline offset)
@ -444,11 +481,10 @@ impl HTMLMediaElement {
// TODO step 5 (playback rate)
// Step 6
self.error.set(None);
// TODO autoplay flag
self.autoplaying.set(true);
// Step 7
let doc = document_from_node(self);
self.invoke_resource_selection_algorithm(doc.base_url());
self.invoke_resource_selection_algorithm();
// TODO step 8 (stop previously playing resource)
}
@ -463,6 +499,11 @@ impl HTMLMediaElementMethods for HTMLMediaElement {
self.ready_state.get()
}
// https://html.spec.whatwg.org/multipage/#dom-media-autoplay
make_bool_getter!(Autoplay, "autoplay");
// https://html.spec.whatwg.org/multipage/#dom-media-autoplay
make_bool_setter!(SetAutoplay, "autoplay");
// https://html.spec.whatwg.org/multipage/#dom-media-src
make_url_getter!(Src, "src");
// https://html.spec.whatwg.org/multipage/#dom-media-src
@ -488,6 +529,60 @@ impl HTMLMediaElementMethods for HTMLMediaElement {
fn GetError(&self) -> Option<Root<MediaError>> {
self.error.get()
}
// https://html.spec.whatwg.org/multipage/#dom-media-play
fn Play(&self) {
// Step 1
if self.network_state.get() == NETWORK_EMPTY {
self.invoke_resource_selection_algorithm();
}
// TODO step 2 (seek backwards)
// TODO step 3 (media controller)
// Step 4
if self.Paused() {
// 4.1
self.paused.set(false);
// TODO 4.2 (show poster)
// 4.3
self.queue_fire_simple_event("play");
// 4.4
let state = self.ready_state.get();
if state == HAVE_NOTHING ||
state == HAVE_METADATA ||
state == HAVE_CURRENT_DATA {
self.queue_fire_simple_event("waiting");
} else {
self.queue_fire_simple_event("playing");
}
// 4.5
self.autoplaying.set(false);
// TODO 4.6 (media controller)
}
}
// https://html.spec.whatwg.org/multipage/#dom-media-pause
fn Pause(&self) {
// Step 1
if self.network_state.get() == NETWORK_EMPTY {
self.invoke_resource_selection_algorithm();
}
// Step 2
self.internal_pause_steps();
}
// https://html.spec.whatwg.org/multipage/#dom-media-paused
fn Paused(&self) -> bool {
self.paused.get()
}
}
impl VirtualMethods for HTMLMediaElement {