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_and_cx;
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_and_cx(
49 Box::new(MediaStream::new_inherited()),
50 global,
51 proto,
52 cx,
53 )
54 }
55
56 pub(crate) fn new_single(
57 cx: &mut js::context::JSContext,
58 global: &GlobalScope,
59 id: MediaStreamId,
60 ty: MediaStreamType,
61 ) -> DomRoot<MediaStream> {
62 let this = Self::new(cx, global);
63 let track = MediaStreamTrack::new(cx, global, id, ty);
64 this.AddTrack(&track);
65 this
66 }
67
68 pub(crate) fn get_tracks(&self) -> Ref<'_, [Dom<MediaStreamTrack>]> {
69 Ref::map(self.tracks.borrow(), |tracks| &**tracks)
70 }
71
72 pub(crate) fn add_track(&self, track: &MediaStreamTrack) {
73 self.tracks.borrow_mut().push(Dom::from_ref(track))
74 }
75}
76
77impl MediaStreamMethods<crate::DomTypeHolder> for MediaStream {
78 fn Constructor(
80 cx: &mut js::context::JSContext,
81 global: &Window,
82 proto: Option<HandleObject>,
83 ) -> Fallible<DomRoot<MediaStream>> {
84 Ok(MediaStream::new_with_proto(cx, &global.global(), proto))
85 }
86
87 fn Constructor_(
89 cx: &mut js::context::JSContext,
90 _: &Window,
91 proto: Option<HandleObject>,
92 stream: &MediaStream,
93 ) -> Fallible<DomRoot<MediaStream>> {
94 Ok(stream.clone_with_proto(cx, proto))
95 }
96
97 fn Constructor__(
99 cx: &mut js::context::JSContext,
100 global: &Window,
101 proto: Option<HandleObject>,
102 tracks: Vec<DomRoot<MediaStreamTrack>>,
103 ) -> Fallible<DomRoot<MediaStream>> {
104 let new = MediaStream::new_with_proto(cx, &global.global(), proto);
105 for track in tracks {
106 new.AddTrack(&track)
109 }
110 Ok(new)
111 }
112
113 fn GetTracks(&self) -> Vec<DomRoot<MediaStreamTrack>> {
115 self.tracks
116 .borrow()
117 .iter()
118 .map(|x| DomRoot::from_ref(&**x))
119 .collect()
120 }
121
122 fn GetAudioTracks(&self) -> Vec<DomRoot<MediaStreamTrack>> {
124 self.tracks
125 .borrow()
126 .iter()
127 .filter(|x| x.ty() == MediaStreamType::Audio)
128 .map(|x| DomRoot::from_ref(&**x))
129 .collect()
130 }
131
132 fn GetVideoTracks(&self) -> Vec<DomRoot<MediaStreamTrack>> {
134 self.tracks
135 .borrow()
136 .iter()
137 .filter(|x| x.ty() == MediaStreamType::Video)
138 .map(|x| DomRoot::from_ref(&**x))
139 .collect()
140 }
141
142 fn GetTrackById(&self, id: DOMString) -> Option<DomRoot<MediaStreamTrack>> {
144 self.tracks
145 .borrow()
146 .iter()
147 .find(|x| x.id().id().to_string() == id)
148 .map(|x| DomRoot::from_ref(&**x))
149 }
150
151 fn AddTrack(&self, track: &MediaStreamTrack) {
153 let existing = self.tracks.borrow().iter().any(|x| x == &track);
154
155 if existing {
156 return;
157 }
158 self.add_track(track)
159 }
160
161 fn RemoveTrack(&self, track: &MediaStreamTrack) {
163 self.tracks.borrow_mut().retain(|x| *x != track);
164 }
165
166 fn Clone(&self, cx: &mut js::context::JSContext) -> DomRoot<MediaStream> {
168 self.clone_with_proto(cx, None)
169 }
170}
171
172impl MediaStream {
173 fn clone_with_proto(
174 &self,
175 cx: &mut js::context::JSContext,
176 proto: Option<HandleObject>,
177 ) -> DomRoot<MediaStream> {
178 let new = MediaStream::new_with_proto(cx, &self.global(), proto);
179 for track in &*self.tracks.borrow() {
180 new.add_track(track)
181 }
182 new
183 }
184}