script/dom/audio/
audioscheduledsourcenode.rs1use std::cell::Cell;
6
7use dom_struct::dom_struct;
8use servo_media::audio::node::{
9 AudioNodeInit, AudioNodeMessage, AudioScheduledSourceNodeMessage, OnEndedCallback,
10};
11
12use crate::dom::audio::audionode::{AudioNode, UnwrappedAudioNodeOptions};
13use crate::dom::audio::baseaudiocontext::BaseAudioContext;
14use crate::dom::bindings::codegen::Bindings::AudioScheduledSourceNodeBinding::AudioScheduledSourceNodeMethods;
15use crate::dom::bindings::error::{Error, Fallible};
16use crate::dom::bindings::inheritance::Castable;
17use crate::dom::bindings::num::Finite;
18use crate::dom::bindings::refcounted::Trusted;
19use crate::dom::bindings::reflector::DomGlobal;
20
21#[dom_struct]
22pub(crate) struct AudioScheduledSourceNode {
23 node: AudioNode,
24 has_start: Cell<bool>,
25 has_stop: Cell<bool>,
26}
27
28impl AudioScheduledSourceNode {
29 #[cfg_attr(crown, allow(crown::unrooted_must_root))]
30 pub(crate) fn new_inherited(
31 node_type: AudioNodeInit,
32 context: &BaseAudioContext,
33 options: UnwrappedAudioNodeOptions,
34 number_of_inputs: u32,
35 number_of_outputs: u32,
36 ) -> Fallible<AudioScheduledSourceNode> {
37 Ok(AudioScheduledSourceNode {
38 node: AudioNode::new_inherited(
39 node_type,
40 context,
41 options,
42 number_of_inputs,
43 number_of_outputs,
44 )?,
45 has_start: Cell::new(false),
46 has_stop: Cell::new(false),
47 })
48 }
49
50 pub(crate) fn node(&self) -> &AudioNode {
51 &self.node
52 }
53
54 pub(crate) fn has_start(&self) -> bool {
55 self.has_start.get()
56 }
57}
58
59impl AudioScheduledSourceNodeMethods<crate::DomTypeHolder> for AudioScheduledSourceNode {
60 event_handler!(ended, GetOnended, SetOnended);
62
63 fn Start(&self, when: Finite<f64>) -> Fallible<()> {
65 if *when < 0. {
66 return Err(Error::Range("'when' must be a positive value".to_owned()));
67 }
68
69 if self.has_start.get() || self.has_stop.get() {
70 return Err(Error::InvalidState);
71 }
72
73 let this = Trusted::new(self);
74 let task_source = self
75 .global()
76 .task_manager()
77 .dom_manipulation_task_source()
78 .to_sendable();
79 let callback = OnEndedCallback::new(move || {
80 task_source.queue(task!(ended: move || {
81 let this = this.root();
82 this.global().task_manager().dom_manipulation_task_source().queue_simple_event(
83 this.upcast(),
84 atom!("ended"),
85 );
86 }));
87 });
88
89 self.node()
90 .message(AudioNodeMessage::AudioScheduledSourceNode(
91 AudioScheduledSourceNodeMessage::RegisterOnEndedCallback(callback),
92 ));
93
94 self.has_start.set(true);
95 self.node
96 .message(AudioNodeMessage::AudioScheduledSourceNode(
97 AudioScheduledSourceNodeMessage::Start(*when),
98 ));
99 Ok(())
100 }
101
102 fn Stop(&self, when: Finite<f64>) -> Fallible<()> {
104 if *when < 0. {
105 return Err(Error::Range("'when' must be a positive value".to_owned()));
106 }
107
108 if !self.has_start.get() {
109 return Err(Error::InvalidState);
110 }
111 self.has_stop.set(true);
112 self.node
113 .message(AudioNodeMessage::AudioScheduledSourceNode(
114 AudioScheduledSourceNodeMessage::Stop(*when),
115 ));
116 Ok(())
117 }
118}