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