diff options
author | sreeise <reeisesean@gmail.com> | 2019-01-04 07:55:38 -0500 |
---|---|---|
committer | sreeise <reeisesean@gmail.com> | 2019-03-03 09:04:50 -0500 |
commit | cac4aa56f77c46db75c9ca1bfdf23be39cfd4604 (patch) | |
tree | 5b58d44fef2d68fb6031bf7c9a959d9e2b85eeb4 /components/script/dom/htmlmediaelement.rs | |
parent | 4d8d54fc00644204768886569959429dd67998a0 (diff) | |
download | servo-cac4aa56f77c46db75c9ca1bfdf23be39cfd4604.tar.gz servo-cac4aa56f77c46db75c9ca1bfdf23be39cfd4604.zip |
Added AudioTrack, AudioTrackList, VideoTrack, VideoTrackList, and TrackEvent interfaces
Diffstat (limited to 'components/script/dom/htmlmediaelement.rs')
-rw-r--r-- | components/script/dom/htmlmediaelement.rs | 121 |
1 files changed, 118 insertions, 3 deletions
diff --git a/components/script/dom/htmlmediaelement.rs b/components/script/dom/htmlmediaelement.rs index c64bd26e57c..703ce9438a7 100644 --- a/components/script/dom/htmlmediaelement.rs +++ b/components/script/dom/htmlmediaelement.rs @@ -4,6 +4,8 @@ use crate::document_loader::{LoadBlocker, LoadType}; use crate::dom::attr::Attr; +use crate::dom::audiotrack::AudioTrack; +use crate::dom::audiotracklist::AudioTrackList; use crate::dom::bindings::cell::DomRefCell; use crate::dom::bindings::codegen::Bindings::AttrBinding::AttrMethods; use crate::dom::bindings::codegen::Bindings::HTMLMediaElementBinding::CanPlayTypeResult; @@ -15,6 +17,7 @@ use crate::dom::bindings::codegen::Bindings::MediaErrorBinding::MediaErrorMethod use crate::dom::bindings::codegen::Bindings::TextTrackBinding::{TextTrackKind, TextTrackMode}; use crate::dom::bindings::codegen::InheritTypes::{ElementTypeId, HTMLElementTypeId}; use crate::dom::bindings::codegen::InheritTypes::{HTMLMediaElementTypeId, NodeTypeId}; +use crate::dom::bindings::codegen::UnionTypes::VideoTrackOrAudioTrackOrTextTrack; use crate::dom::bindings::error::{Error, ErrorResult, Fallible}; use crate::dom::bindings::inheritance::Castable; use crate::dom::bindings::num::Finite; @@ -25,6 +28,7 @@ use crate::dom::bindings::str::{DOMString, USVString}; use crate::dom::blob::Blob; use crate::dom::document::Document; use crate::dom::element::{AttributeMutation, Element}; +use crate::dom::event::Event; use crate::dom::eventtarget::EventTarget; use crate::dom::globalscope::GlobalScope; use crate::dom::htmlelement::HTMLElement; @@ -37,6 +41,9 @@ use crate::dom::promise::Promise; use crate::dom::texttrack::TextTrack; use crate::dom::texttracklist::TextTrackList; use crate::dom::timeranges::{TimeRanges, TimeRangesContainer}; +use crate::dom::trackevent::TrackEvent; +use crate::dom::videotrack::VideoTrack; +use crate::dom::videotracklist::VideoTrackList; use crate::dom::virtualmethods::VirtualMethods; use crate::fetch::FetchCanceller; use crate::microtask::{Microtask, MicrotaskRunnable}; @@ -206,6 +213,10 @@ pub struct HTMLMediaElement { /// https://html.spec.whatwg.org/multipage/#dom-media-played #[ignore_malloc_size_of = "Rc"] played: DomRefCell<TimeRangesContainer>, + // https://html.spec.whatwg.org/multipage/#dom-media-audiotracks + audio_tracks_list: MutNullableDom<AudioTrackList>, + // https://html.spec.whatwg.org/multipage/#dom-media-videotracks + video_tracks_list: MutNullableDom<VideoTrackList>, /// https://html.spec.whatwg.org/multipage/#dom-media-texttracks text_tracks_list: MutNullableDom<TextTrackList>, /// Time of last timeupdate notification. @@ -268,6 +279,8 @@ impl HTMLMediaElement { seeking: Cell::new(false), resource_url: DomRefCell::new(None), played: DomRefCell::new(TimeRangesContainer::new()), + audio_tracks_list: Default::default(), + video_tracks_list: Default::default(), text_tracks_list: Default::default(), next_timeupdate_event: Cell::new(time::get_time() + Duration::milliseconds(250)), current_fetch_context: DomRefCell::new(None), @@ -803,7 +816,8 @@ impl HTMLMediaElement { ))); // Step 2. - // FIXME(nox): Forget the media-resource-specific tracks. + this.AudioTracks().clear(); + this.VideoTracks().clear(); // Step 3. this.network_state.set(NetworkState::NoSource); @@ -904,7 +918,8 @@ impl HTMLMediaElement { // FIXME(nox): Detach MediaSource media provider object. // Step 6.4. - // FIXME(nox): Forget the media-resource-specific tracks. + self.AudioTracks().clear(); + self.VideoTracks().clear(); // Step 6.5. if self.ready_state.get() != ReadyState::HaveNothing { @@ -1227,6 +1242,92 @@ impl HTMLMediaElement { }, PlayerEvent::MetadataUpdated(ref metadata) => { // https://html.spec.whatwg.org/multipage/#media-data-processing-steps-list + // => If the media resource is found to have an audio track + if !metadata.audio_tracks.is_empty() { + for (i, _track) in metadata.audio_tracks.iter().enumerate() { + // Step 1. + let kind = match i { + 0 => DOMString::from("main"), + _ => DOMString::new(), + }; + let window = window_from_node(self); + let audio_track = AudioTrack::new( + &window, + DOMString::new(), + kind, + DOMString::new(), + DOMString::new(), + ); + + // Steps 2. & 3. + self.AudioTracks().add(&audio_track); + + // Step 4 + // https://www.w3.org/TR/media-frags/#media-fragment-syntax + // https://github.com/servo/servo/issues/22366 + + // Step 5. & 6, + if self.AudioTracks().enabled_index().is_none() { + self.AudioTracks() + .set_enabled(self.AudioTracks().len() - 1, true); + } + + // Steps 7. + let event = TrackEvent::new( + &self.global(), + atom!("addtrack"), + false, + false, + &Some(VideoTrackOrAudioTrackOrTextTrack::AudioTrack(audio_track)), + ); + + event.upcast::<Event>().fire(self.upcast::<EventTarget>()); + } + } + + // => If the media resource is found to have a video track + if !metadata.video_tracks.is_empty() { + for (i, _track) in metadata.video_tracks.iter().enumerate() { + // Step 1. + let kind = match i { + 0 => DOMString::from("main"), + _ => DOMString::new(), + }; + let window = window_from_node(self); + let video_track = VideoTrack::new( + &window, + DOMString::new(), + kind, + DOMString::new(), + DOMString::new(), + ); + + // Steps 2. & 3. + self.VideoTracks().add(&video_track); + + // Step 4. + // https://www.w3.org/TR/media-frags/#media-fragment-syntax + // https://github.com/servo/servo/issues/22366 + + // Step 5. & 6. + if self.VideoTracks().selected_index().is_none() { + self.VideoTracks() + .set_selected(self.VideoTracks().len() - 1, true); + } + + // Steps 7. + let event = TrackEvent::new( + &self.global(), + atom!("addtrack"), + false, + false, + &Some(VideoTrackOrAudioTrackOrTextTrack::VideoTrack(video_track)), + ); + + event.upcast::<Event>().fire(self.upcast::<EventTarget>()); + } + } + // => "Once enough of the media data has been fetched to determine the duration..." // Step 1. // servo-media owns the media timeline. @@ -1287,7 +1388,7 @@ impl HTMLMediaElement { // https://www.w3.org/TR/media-frags/#media-fragment-syntax // https://github.com/servo/media/issues/156 - // XXX Steps 12 and 13 require audio and video tracks support. + // Step 12 & 13 are already handled by the earlier media track processing. }, PlayerEvent::NeedData => { // The player needs more data. @@ -1702,6 +1803,20 @@ impl HTMLMediaElementMethods for HTMLMediaElement { TimeRanges::new(self.global().as_window(), buffered) } + // https://html.spec.whatwg.org/multipage/#dom-media-audiotracks + fn AudioTracks(&self) -> DomRoot<AudioTrackList> { + let window = window_from_node(self); + self.audio_tracks_list + .or_init(|| AudioTrackList::new(&window, &[])) + } + + // https://html.spec.whatwg.org/multipage/#dom-media-videotracks + fn VideoTracks(&self) -> DomRoot<VideoTrackList> { + let window = window_from_node(self); + self.video_tracks_list + .or_init(|| VideoTrackList::new(&window, &[])) + } + // https://html.spec.whatwg.org/multipage/#dom-media-texttracks fn TextTracks(&self) -> DomRoot<TextTrackList> { let window = window_from_node(self); |