aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock10
-rw-r--r--components/atoms/static_atoms.txt1
-rw-r--r--components/script/dom/htmlmediaelement.rs109
-rw-r--r--components/script/dom/webidls/HTMLMediaElement.webidl4
-rw-r--r--tests/wpt/metadata/html/dom/interfaces.https.html.ini32
-rw-r--r--tests/wpt/metadata/html/semantics/embedded-content/media-elements/playing-the-media-resource/playbackRate.html.ini27
6 files changed, 126 insertions, 57 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 59cc45d04a9..aa0c4abfd1d 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3513,7 +3513,7 @@ dependencies = [
[[package]]
name = "servo-media"
version = "0.1.0"
-source = "git+https://github.com/servo/media#352072f33b6d118f89aa4ccf000ceaf360a5f663"
+source = "git+https://github.com/servo/media#35014baeb603b56b1b8b4de75919c58f7390cc30"
dependencies = [
"servo-media-audio 0.1.0 (git+https://github.com/servo/media)",
"servo-media-gstreamer 0.1.0 (git+https://github.com/servo/media)",
@@ -3523,7 +3523,7 @@ dependencies = [
[[package]]
name = "servo-media-audio"
version = "0.1.0"
-source = "git+https://github.com/servo/media#352072f33b6d118f89aa4ccf000ceaf360a5f663"
+source = "git+https://github.com/servo/media#35014baeb603b56b1b8b4de75919c58f7390cc30"
dependencies = [
"boxfnonce 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"byte-slice-cast 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -3540,7 +3540,7 @@ dependencies = [
[[package]]
name = "servo-media-gstreamer"
version = "0.1.0"
-source = "git+https://github.com/servo/media#352072f33b6d118f89aa4ccf000ceaf360a5f663"
+source = "git+https://github.com/servo/media#35014baeb603b56b1b8b4de75919c58f7390cc30"
dependencies = [
"byte-slice-cast 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"glib 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -3559,7 +3559,7 @@ dependencies = [
[[package]]
name = "servo-media-player"
version = "0.1.0"
-source = "git+https://github.com/servo/media#352072f33b6d118f89aa4ccf000ceaf360a5f663"
+source = "git+https://github.com/servo/media#35014baeb603b56b1b8b4de75919c58f7390cc30"
dependencies = [
"ipc-channel 0.11.2 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -3646,7 +3646,7 @@ dependencies = [
[[package]]
name = "servo_media_derive"
version = "0.1.0"
-source = "git+https://github.com/servo/media#352072f33b6d118f89aa4ccf000ceaf360a5f663"
+source = "git+https://github.com/servo/media#35014baeb603b56b1b8b4de75919c58f7390cc30"
dependencies = [
"proc-macro2 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
diff --git a/components/atoms/static_atoms.txt b/components/atoms/static_atoms.txt
index 937d0ea620e..ebe3e890145 100644
--- a/components/atoms/static_atoms.txt
+++ b/components/atoms/static_atoms.txt
@@ -67,6 +67,7 @@ print
progress
radio
range
+ratechange
readystatechange
reftest-wait
rejectionhandled
diff --git a/components/script/dom/htmlmediaelement.rs b/components/script/dom/htmlmediaelement.rs
index ee43992a27f..2bde1cf4062 100644
--- a/components/script/dom/htmlmediaelement.rs
+++ b/components/script/dom/htmlmediaelement.rs
@@ -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>
@@ -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(),
@@ -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
@@ -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(),
@@ -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
@@ -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
@@ -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);
@@ -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()
diff --git a/components/script/dom/webidls/HTMLMediaElement.webidl b/components/script/dom/webidls/HTMLMediaElement.webidl
index db67a81e2a1..8d927e91cac 100644
--- a/components/script/dom/webidls/HTMLMediaElement.webidl
+++ b/components/script/dom/webidls/HTMLMediaElement.webidl
@@ -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;
diff --git a/tests/wpt/metadata/html/dom/interfaces.https.html.ini b/tests/wpt/metadata/html/dom/interfaces.https.html.ini
index 6affb3327d9..18d6ddab4c4 100644
--- a/tests/wpt/metadata/html/dom/interfaces.https.html.ini
+++ b/tests/wpt/metadata/html/dom/interfaces.https.html.ini
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
diff --git a/tests/wpt/metadata/html/semantics/embedded-content/media-elements/playing-the-media-resource/playbackRate.html.ini b/tests/wpt/metadata/html/semantics/embedded-content/media-elements/playing-the-media-resource/playbackRate.html.ini
deleted file mode 100644
index 666997e01de..00000000000
--- a/tests/wpt/metadata/html/semantics/embedded-content/media-elements/playing-the-media-resource/playbackRate.html.ini
+++ /dev/null
@@ -1,27 +0,0 @@
-[playbackRate.html]
- type: testharness
- expected: TIMEOUT
- [playbackRate initial value]
- expected: FAIL
-
- [setting playbackRate]
- expected: TIMEOUT
-
- [playbackRate set to small positive value]
- expected: TIMEOUT
-
- [playbackRate set to large positive value]
- expected: TIMEOUT
-
- [playbackRate set to small negative value]
- expected: TIMEOUT
-
- [playbackRate set to large negative value]
- expected: TIMEOUT
-
- [playbackRate set to 0]
- expected: TIMEOUT
-
- [playbackRate set to -1]
- expected: TIMEOUT
-