web_audio_api/context/
mod.rs1use std::{any::Any, ops::Range};
4
5mod base;
6pub use base::*;
7
8mod concrete_base;
9pub use concrete_base::*;
10
11#[cfg(feature = "diagnostics")]
12mod diagnostics;
13#[cfg(feature = "diagnostics")]
14pub use diagnostics::*;
15
16mod offline;
17pub use offline::*;
18
19mod online;
20pub use online::*;
21
22pub(crate) const DESTINATION_NODE_ID: AudioNodeId = AudioNodeId(0);
25const LISTENER_NODE_ID: AudioNodeId = AudioNodeId(1);
27const LISTENER_PARAM_IDS: Range<u64> = 2..11;
29pub(crate) const LISTENER_AUDIO_PARAM_IDS: [AudioParamId; 9] = [
31 AudioParamId(2),
32 AudioParamId(3),
33 AudioParamId(4),
34 AudioParamId(5),
35 AudioParamId(6),
36 AudioParamId(7),
37 AudioParamId(8),
38 AudioParamId(9),
39 AudioParamId(10),
40];
41
42#[derive(Hash, PartialEq, Eq, Clone, Copy)]
46pub(crate) struct AudioNodeId(pub u64);
47
48impl std::fmt::Debug for AudioNodeId {
49 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
50 write!(f, "AudioNodeId({})", self.0)
51 }
52}
53
54#[derive(Debug)]
58pub struct AudioParamId(u64);
59
60impl From<&AudioParamId> for AudioNodeId {
62 fn from(i: &AudioParamId) -> Self {
63 Self(i.0)
64 }
65}
66
67#[derive(Debug, Copy, Clone, PartialEq, Eq)]
69pub enum AudioContextState {
70 Suspended,
73 Running,
75 Closed,
78}
79
80impl From<u8> for AudioContextState {
81 fn from(value: u8) -> Self {
82 match value {
83 0 => Self::Suspended,
84 1 => Self::Running,
85 2 => Self::Closed,
86 _ => unreachable!(),
87 }
88 }
89}
90
91pub struct AudioContextRegistration {
99 context: ConcreteBaseAudioContext,
101 id: AudioNodeId,
103}
104
105impl std::fmt::Debug for AudioContextRegistration {
106 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
107 f.debug_struct("AudioContextRegistration")
108 .field("id", &self.id)
109 .field(
110 "context",
111 &format!("BaseAudioContext@{}", self.context.address()),
112 )
113 .finish()
114 }
115}
116
117impl AudioContextRegistration {
118 #[must_use]
120 pub(crate) fn id(&self) -> AudioNodeId {
121 self.id
122 }
123
124 #[must_use]
126 pub(crate) fn context(&self) -> &ConcreteBaseAudioContext {
127 &self.context
128 }
129
130 pub(crate) fn post_message<M: Any + Send + 'static>(&self, msg: M) {
135 let wrapped = crate::message::ControlMessage::NodeMessage {
136 id: self.id,
137 msg: llq::Node::new(Box::new(msg)),
138 };
139 self.context.send_control_msg(wrapped);
140 }
141}
142
143impl Drop for AudioContextRegistration {
144 fn drop(&mut self) {
145 self.context.mark_node_dropped(self.id);
146 }
147}
148
149#[cfg(test)]
150mod tests {
151 use super::*;
152 use crate::node::AudioNode;
153
154 fn require_send_sync_static<T: Send + Sync + 'static>(_: T) {}
155
156 #[test]
157 fn test_audio_context_registration_traits() {
158 let context = OfflineAudioContext::new(1, 1, 44100.);
159 let registration = context.mock_registration();
160
161 require_send_sync_static(registration);
164 }
165
166 #[test]
167 fn test_offline_audio_context_send_sync() {
168 let context = OfflineAudioContext::new(1, 1, 44100.);
169 require_send_sync_static(context);
170 }
171
172 #[test]
173 fn test_online_audio_context_send_sync() {
174 let options = AudioContextOptions {
175 sink_id: "none".into(),
176 ..AudioContextOptions::default()
177 };
178 let context = AudioContext::new(options);
179 require_send_sync_static(context);
180 }
181
182 #[test]
183 fn test_context_equals() {
184 let context = OfflineAudioContext::new(1, 48000, 96000.);
185 let dest = context.destination();
186 assert!(dest.context() == context.base());
187 }
188}