diff options
author | Fernando Jiménez Moreno <ferjmoreno@gmail.com> | 2018-10-22 16:01:00 +0200 |
---|---|---|
committer | Fernando Jiménez Moreno <ferjmoreno@gmail.com> | 2018-10-26 10:19:52 +0200 |
commit | 75407822bc6840da508ccf5cd80d0115ee91d2aa (patch) | |
tree | e4329b77569c6d610daf9597e924437817a42bee /components/script/dom/htmlmediaelement.rs | |
parent | 2db141fb8b7c941d77ffa0ff32b872679b55ea2b (diff) | |
download | servo-75407822bc6840da508ccf5cd80d0115ee91d2aa.tar.gz servo-75407822bc6840da508ccf5cd80d0115ee91d2aa.zip |
HTMLMediaElement seeking
Diffstat (limited to 'components/script/dom/htmlmediaelement.rs')
-rw-r--r-- | components/script/dom/htmlmediaelement.rs | 111 |
1 files changed, 106 insertions, 5 deletions
diff --git a/components/script/dom/htmlmediaelement.rs b/components/script/dom/htmlmediaelement.rs index f594608563c..0f67d7a6fd2 100644 --- a/components/script/dom/htmlmediaelement.rs +++ b/components/script/dom/htmlmediaelement.rs @@ -170,10 +170,12 @@ pub struct HTMLMediaElement { show_poster: Cell<bool>, /// https://html.spec.whatwg.org/multipage/#dom-media-duration duration: Cell<f64>, - /// https://html.spec.whatwg.org/multipage/media.html#official-playback-position + /// https://html.spec.whatwg.org/multipage/#official-playback-position playback_position: Cell<f64>, - /// https://html.spec.whatwg.org/multipage/media.html#default-playback-start-position + /// https://html.spec.whatwg.org/multipage/#default-playback-start-position default_playback_start_position: Cell<f64>, + /// https://html.spec.whatwg.org/multipage/#dom-media-seeking + seeking: Cell<bool>, } /// <https://html.spec.whatwg.org/multipage/#dom-media-networkstate> @@ -223,6 +225,7 @@ impl HTMLMediaElement { duration: Cell::new(f64::NAN), playback_position: Cell::new(0.), default_playback_start_position: Cell::new(0.), + seeking: Cell::new(false), } } @@ -969,8 +972,69 @@ impl HTMLMediaElement { } // https://html.spec.whatwg.org/multipage/#dom-media-seek - fn seek(&self, _time: f64, _approximate_for_speed: bool) { - // XXX + fn seek(&self, time: f64, approximate_for_speed: bool) { + // Step 1. + self.show_poster.set(false); + + // Step 2. + if self.ready_state.get() == ReadyState::HaveNothing { + return; + } + + // Step 3. + if self.seeking.get() { + // This will cancel only the sync part of the seek algorithm. + self.generation_id.set(self.generation_id.get() + 1); + } + + // Step 4. + // The flag will be cleared when the media engine tells us the seek was done. + self.seeking.set(true); + + // Step 5. + // XXX(ferjm) The rest of the steps should be run in parallel, so seeking cancelation + // can be done properly. No other browser does it yet anyway. + + // Step 6. + let time = f64::min(time, self.Duration()); + + // Step 7. + let time = f64::max(time, 0.); + + // Step 8. + // XXX(ferjm) seekable attribute. + + // Step 9. + let accurate = !approximate_for_speed; + + // Step 10. + let window = window_from_node(self); + let task_source = window.media_element_task_source(); + task_source.queue_simple_event(self.upcast(), atom!("seeking"), &window); + + // Step 11. + // XXX self.player.seek(time, accurate); + + // The rest of the steps are handled when the media engine signals a + // ready state change or otherwise satisfies seek completion and signals + // a position change. + } + + // https://html.spec.whatwg.org/multipage/#dom-media-seek + fn seek_sync(&self) { + // Step 14. + self.seeking.set(false); + + // Step 15. + self.time_marches_on(); + + // Step 16. + let window = window_from_node(self); + let task_source = window.media_element_task_source(); + task_source.queue_simple_event(self.upcast(), atom!("timeupdate"), &window); + + // Step 17. + task_source.queue_simple_event(self.upcast(), atom!("seeked"), &window); } fn setup_media_player(&self) -> Result<(), ServoMediaError> { @@ -1043,7 +1107,10 @@ impl HTMLMediaElement { // Step 8. if self.default_playback_start_position.get() > 0. { - self.seek(self.default_playback_start_position.get(), /* approximate_for_speed*/ false); + self.seek( + self.default_playback_start_position.get(), + /* approximate_for_speed*/ false, + ); _jumped = true; } @@ -1084,6 +1151,20 @@ impl HTMLMediaElement { PlayerEvent::FrameUpdated => { self.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage); }, + PlayerEvent::SeekData(_) => { + // XXX byte-range request + }, + PlayerEvent::SeekDone(_) => { + // Continuation of + // https://html.spec.whatwg.org/multipage/#dom-media-seek + + // Step 13. + let task = MediaElementMicrotask::SeekedTask { + elem: DomRoot::from_ref(self), + generation_id: self.generation_id.get(), + }; + ScriptThread::await_stable_state(Microtask::MediaElement(task)); + }, PlayerEvent::Error => { self.error.set(Some(&*MediaError::new( &*window_from_node(self), @@ -1206,6 +1287,14 @@ impl HTMLMediaElementMethods for HTMLMediaElement { self.seek(*time, /* approximate_for_speed */ false); } } + + fn Seeking(&self) -> bool { + self.seeking.get() + } + + fn FastSeek(&self, time: Finite<f64>) { + self.seek(*time, /* approximat_for_speed */ true); + } } impl VirtualMethods for HTMLMediaElement { @@ -1263,6 +1352,10 @@ pub enum MediaElementMicrotask { PauseIfNotInDocumentTask { elem: DomRoot<HTMLMediaElement>, }, + SeekedTask { + elem: DomRoot<HTMLMediaElement>, + generation_id: u32, + }, } impl MicrotaskRunnable for MediaElementMicrotask { @@ -1282,6 +1375,14 @@ impl MicrotaskRunnable for MediaElementMicrotask { elem.internal_pause_steps(); } }, + &MediaElementMicrotask::SeekedTask { + ref elem, + generation_id, + } => { + if generation_id == elem.generation_id.get() { + elem.seek_sync(); + } + }, } } } |