script/dom/media/
mediastream.rs1use dom_struct::dom_struct;
6use js::rust::HandleObject;
7use script_bindings::cell::{DomRefCell, Ref};
8use script_bindings::reflector::reflect_dom_object_with_proto;
9use servo_media::streams::MediaStreamType;
10use servo_media::streams::registry::MediaStreamId;
11
12use crate::dom::bindings::codegen::Bindings::MediaStreamBinding::MediaStreamMethods;
13use crate::dom::bindings::error::Fallible;
14use crate::dom::bindings::reflector::DomGlobal;
15use crate::dom::bindings::root::{Dom, DomRoot};
16use crate::dom::bindings::str::DOMString;
17use crate::dom::eventtarget::EventTarget;
18use crate::dom::globalscope::GlobalScope;
19use crate::dom::media::mediastreamtrack::MediaStreamTrack;
20use crate::dom::window::Window;
21
22#[dom_struct]
23pub(crate) struct MediaStream {
24 eventtarget: EventTarget,
25 tracks: DomRefCell<Vec<Dom<MediaStreamTrack>>>,
26}
27
28impl MediaStream {
29 pub(crate) fn new_inherited() -> MediaStream {
30 MediaStream {
31 eventtarget: EventTarget::new_inherited(),
32 tracks: DomRefCell::new(vec![]),
33 }
34 }
35
36 pub(crate) fn new(
37 cx: &mut js::context::JSContext,
38 global: &GlobalScope,
39 ) -> DomRoot<MediaStream> {
40 Self::new_with_proto(cx, global, None)
41 }
42
43 fn new_with_proto(
44 cx: &mut js::context::JSContext,
45 global: &GlobalScope,
46 proto: Option<HandleObject>,
47 ) -> DomRoot<MediaStream> {
48 reflect_dom_object_with_proto(cx, Box::new(MediaStream::new_inherited()), global, proto)
49 }
50
51 pub(crate) fn new_single(
52 cx: &mut js::context::JSContext,
53 global: &GlobalScope,
54 id: MediaStreamId,
55 ty: MediaStreamType,
56 ) -> DomRoot<MediaStream> {
57 let this = Self::new(cx, global);
58 let track = MediaStreamTrack::new(cx, global, id, ty);
59 this.AddTrack(&track);
60 this
61 }
62
63 pub(crate) fn get_tracks(&self) -> Ref<'_, [Dom<MediaStreamTrack>]> {
64 Ref::map(self.tracks.borrow(), |tracks| &**tracks)
65 }
66
67 pub(crate) fn add_track(&self, track: &MediaStreamTrack) {
68 self.tracks.borrow_mut().push(Dom::from_ref(track))
69 }
70}
71
72impl MediaStreamMethods<crate::DomTypeHolder> for MediaStream {
73 fn Constructor(
75 cx: &mut js::context::JSContext,
76 global: &Window,
77 proto: Option<HandleObject>,
78 ) -> Fallible<DomRoot<MediaStream>> {
79 Ok(MediaStream::new_with_proto(cx, &global.global(), proto))
80 }
81
82 fn Constructor_(
84 cx: &mut js::context::JSContext,
85 _: &Window,
86 proto: Option<HandleObject>,
87 stream: &MediaStream,
88 ) -> Fallible<DomRoot<MediaStream>> {
89 Ok(stream.clone_with_proto(cx, proto))
90 }
91
92 fn Constructor__(
94 cx: &mut js::context::JSContext,
95 global: &Window,
96 proto: Option<HandleObject>,
97 tracks: Vec<DomRoot<MediaStreamTrack>>,
98 ) -> Fallible<DomRoot<MediaStream>> {
99 let new = MediaStream::new_with_proto(cx, &global.global(), proto);
100 for track in tracks {
101 new.AddTrack(&track)
104 }
105 Ok(new)
106 }
107
108 fn GetTracks(&self) -> Vec<DomRoot<MediaStreamTrack>> {
110 self.tracks
111 .borrow()
112 .iter()
113 .map(|x| DomRoot::from_ref(&**x))
114 .collect()
115 }
116
117 fn GetAudioTracks(&self) -> Vec<DomRoot<MediaStreamTrack>> {
119 self.tracks
120 .borrow()
121 .iter()
122 .filter(|x| x.ty() == MediaStreamType::Audio)
123 .map(|x| DomRoot::from_ref(&**x))
124 .collect()
125 }
126
127 fn GetVideoTracks(&self) -> Vec<DomRoot<MediaStreamTrack>> {
129 self.tracks
130 .borrow()
131 .iter()
132 .filter(|x| x.ty() == MediaStreamType::Video)
133 .map(|x| DomRoot::from_ref(&**x))
134 .collect()
135 }
136
137 fn GetTrackById(&self, id: DOMString) -> Option<DomRoot<MediaStreamTrack>> {
139 self.tracks
140 .borrow()
141 .iter()
142 .find(|x| x.id().id().to_string() == id)
143 .map(|x| DomRoot::from_ref(&**x))
144 }
145
146 fn AddTrack(&self, track: &MediaStreamTrack) {
148 let existing = self.tracks.borrow().iter().any(|x| x == &track);
149
150 if existing {
151 return;
152 }
153 self.add_track(track)
154 }
155
156 fn RemoveTrack(&self, track: &MediaStreamTrack) {
158 self.tracks.borrow_mut().retain(|x| *x != track);
159 }
160
161 fn Clone(&self, cx: &mut js::context::JSContext) -> DomRoot<MediaStream> {
163 self.clone_with_proto(cx, None)
164 }
165}
166
167impl MediaStream {
168 fn clone_with_proto(
169 &self,
170 cx: &mut js::context::JSContext,
171 proto: Option<HandleObject>,
172 ) -> DomRoot<MediaStream> {
173 let new = MediaStream::new_with_proto(cx, &self.global(), proto);
174 for track in &*self.tracks.borrow() {
175 new.add_track(track)
176 }
177 new
178 }
179}