1use dom_struct::dom_struct;
6use js::rust::HandleObject;
7use stylo_atoms::Atom;
8
9use crate::dom::audio::audiotrack::AudioTrack;
10use crate::dom::bindings::codegen::Bindings::EventBinding::Event_Binding::EventMethods;
11use crate::dom::bindings::codegen::Bindings::TrackEventBinding;
12use crate::dom::bindings::codegen::Bindings::TrackEventBinding::TrackEventMethods;
13use crate::dom::bindings::codegen::UnionTypes::VideoTrackOrAudioTrackOrTextTrack;
14use crate::dom::bindings::error::Fallible;
15use crate::dom::bindings::inheritance::Castable;
16use crate::dom::bindings::reflector::reflect_dom_object_with_proto;
17use crate::dom::bindings::root::{Dom, DomRoot};
18use crate::dom::bindings::str::DOMString;
19use crate::dom::event::Event;
20use crate::dom::texttrack::TextTrack;
21use crate::dom::videotrack::VideoTrack;
22use crate::dom::window::Window;
23use crate::script_runtime::CanGc;
24
25#[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)]
26#[derive(JSTraceable, MallocSizeOf)]
27enum MediaTrack {
28 Video(Dom<VideoTrack>),
29 Audio(Dom<AudioTrack>),
30 Text(Dom<TextTrack>),
31}
32
33#[dom_struct]
34pub(crate) struct TrackEvent {
35 event: Event,
36 track: Option<MediaTrack>,
37}
38
39impl TrackEvent {
40 #[allow(non_snake_case)]
41 #[cfg_attr(crown, allow(crown::unrooted_must_root))]
42 fn new_inherited(track: &Option<VideoTrackOrAudioTrackOrTextTrack>) -> TrackEvent {
43 let media_track = match track {
44 Some(VideoTrackOrAudioTrackOrTextTrack::VideoTrack(VideoTrack)) => {
45 Some(MediaTrack::Video(Dom::from_ref(VideoTrack)))
46 },
47 Some(VideoTrackOrAudioTrackOrTextTrack::AudioTrack(AudioTrack)) => {
48 Some(MediaTrack::Audio(Dom::from_ref(AudioTrack)))
49 },
50 Some(VideoTrackOrAudioTrackOrTextTrack::TextTrack(TextTrack)) => {
51 Some(MediaTrack::Text(Dom::from_ref(TextTrack)))
52 },
53 None => None,
54 };
55
56 TrackEvent {
57 event: Event::new_inherited(),
58 track: media_track,
59 }
60 }
61
62 pub(crate) fn new(
63 window: &Window,
64 type_: Atom,
65 bubbles: bool,
66 cancelable: bool,
67 track: &Option<VideoTrackOrAudioTrackOrTextTrack>,
68 can_gc: CanGc,
69 ) -> DomRoot<TrackEvent> {
70 Self::new_with_proto(window, None, type_, bubbles, cancelable, track, can_gc)
71 }
72
73 fn new_with_proto(
74 window: &Window,
75 proto: Option<HandleObject>,
76 type_: Atom,
77 bubbles: bool,
78 cancelable: bool,
79 track: &Option<VideoTrackOrAudioTrackOrTextTrack>,
80 can_gc: CanGc,
81 ) -> DomRoot<TrackEvent> {
82 let te = reflect_dom_object_with_proto(
83 Box::new(TrackEvent::new_inherited(track)),
84 window,
85 proto,
86 can_gc,
87 );
88 {
89 let event = te.upcast::<Event>();
90 event.init_event(type_, bubbles, cancelable);
91 }
92 te
93 }
94}
95
96impl TrackEventMethods<crate::DomTypeHolder> for TrackEvent {
97 fn Constructor(
99 window: &Window,
100 proto: Option<HandleObject>,
101 can_gc: CanGc,
102 type_: DOMString,
103 init: &TrackEventBinding::TrackEventInit,
104 ) -> Fallible<DomRoot<TrackEvent>> {
105 Ok(TrackEvent::new_with_proto(
106 window,
107 proto,
108 Atom::from(type_),
109 init.parent.bubbles,
110 init.parent.cancelable,
111 &init.track,
112 can_gc,
113 ))
114 }
115
116 #[allow(non_snake_case)]
118 fn GetTrack(&self) -> Option<VideoTrackOrAudioTrackOrTextTrack> {
119 match &self.track {
120 Some(MediaTrack::Video(VideoTrack)) => Some(
121 VideoTrackOrAudioTrackOrTextTrack::VideoTrack(DomRoot::from_ref(VideoTrack)),
122 ),
123 Some(MediaTrack::Audio(AudioTrack)) => Some(
124 VideoTrackOrAudioTrackOrTextTrack::AudioTrack(DomRoot::from_ref(AudioTrack)),
125 ),
126 Some(MediaTrack::Text(TextTrack)) => Some(
127 VideoTrackOrAudioTrackOrTextTrack::TextTrack(DomRoot::from_ref(TextTrack)),
128 ),
129 None => None,
130 }
131 }
132
133 fn IsTrusted(&self) -> bool {
135 self.event.IsTrusted()
136 }
137}