diff options
-rw-r--r-- | Cargo.lock | 10 | ||||
-rw-r--r-- | components/atoms/static_atoms.txt | 1 | ||||
-rw-r--r-- | components/script/dom/htmlmediaelement.rs | 109 | ||||
-rw-r--r-- | components/script/dom/webidls/HTMLMediaElement.webidl | 4 | ||||
-rw-r--r-- | tests/wpt/metadata/html/dom/interfaces.https.html.ini | 32 | ||||
-rw-r--r-- | tests/wpt/metadata/html/semantics/embedded-content/media-elements/playing-the-media-resource/playbackRate.html.ini | 27 |
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 - |