Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement basic <media> infrastructure #8454

Merged
merged 13 commits into from May 4, 2016

Implement play, pause, paused, and autoplay APIs.

  • Loading branch information
jdm committed May 3, 2016
commit e3db11fd8b5e75dd566d904413ac3d74ad683598
@@ -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,15 +308,16 @@ 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);

// TODO step 2 (show poster)
// 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 {
@@ -38,16 +38,16 @@ interface HTMLMediaElement : HTMLElement {
//void fastSeek(double time);
//readonly attribute unrestricted double duration;
//Date getStartDate();
//readonly attribute boolean paused;
readonly attribute boolean paused;
// attribute double defaultPlaybackRate;
// attribute double playbackRate;
//readonly attribute TimeRanges played;
//readonly attribute TimeRanges seekable;
//readonly attribute boolean ended;
// attribute boolean autoplay;
attribute boolean autoplay;
// attribute boolean loop;
//void play();
//void pause();
void play();
void pause();

// media controller
// attribute DOMString mediaGroup;
@@ -2646,9 +2646,6 @@
[HTMLMediaElement interface: document.createElement("video") must inherit property "getStartDate" with the proper type (23)]
expected: FAIL

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

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

@@ -2664,18 +2661,9 @@
[HTMLMediaElement interface: document.createElement("video") must inherit property "ended" with the proper type (29)]
expected: FAIL

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

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

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

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

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

@@ -2736,9 +2724,6 @@
[HTMLMediaElement interface: document.createElement("audio") must inherit property "getStartDate" with the proper type (23)]
expected: FAIL

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

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

@@ -2754,18 +2739,9 @@
[HTMLMediaElement interface: document.createElement("audio") must inherit property "ended" with the proper type (29)]
expected: FAIL

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

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

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

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

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

@@ -3078,9 +3054,6 @@
[HTMLMediaElement interface: operation getStartDate()]
expected: FAIL

[HTMLMediaElement interface: attribute paused]
expected: FAIL

[HTMLMediaElement interface: attribute defaultPlaybackRate]
expected: FAIL

@@ -3096,18 +3069,9 @@
[HTMLMediaElement interface: attribute ended]
expected: FAIL

[HTMLMediaElement interface: attribute autoplay]
expected: FAIL

[HTMLMediaElement interface: attribute loop]
expected: FAIL

[HTMLMediaElement interface: operation play()]
expected: FAIL

[HTMLMediaElement interface: operation pause()]
expected: FAIL

[HTMLMediaElement interface: attribute mediaGroup]
expected: FAIL

ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.