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
11mod offline;
12pub use offline::*;
13
14mod online;
15pub use online::*;
16
17pub(crate) const DESTINATION_NODE_ID: AudioNodeId = AudioNodeId(0);
20const LISTENER_NODE_ID: AudioNodeId = AudioNodeId(1);
22const LISTENER_PARAM_IDS: Range<u64> = 2..11;
24pub(crate) const LISTENER_AUDIO_PARAM_IDS: [AudioParamId; 9] = [
26 AudioParamId(2),
27 AudioParamId(3),
28 AudioParamId(4),
29 AudioParamId(5),
30 AudioParamId(6),
31 AudioParamId(7),
32 AudioParamId(8),
33 AudioParamId(9),
34 AudioParamId(10),
35];
36
37#[derive(Hash, PartialEq, Eq, Clone, Copy)]
41pub(crate) struct AudioNodeId(pub u64);
42
43impl std::fmt::Debug for AudioNodeId {
44 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
45 write!(f, "AudioNodeId({})", self.0)
46 }
47}
48
49#[derive(Debug)]
53pub struct AudioParamId(u64);
54
55impl From<&AudioParamId> for AudioNodeId {
57 fn from(i: &AudioParamId) -> Self {
58 Self(i.0)
59 }
60}
61
62#[derive(Debug, Copy, Clone, PartialEq, Eq)]
64pub enum AudioContextState {
65 Suspended,
68 Running,
70 Closed,
73}
74
75impl From<u8> for AudioContextState {
76 fn from(value: u8) -> Self {
77 match value {
78 0 => Self::Suspended,
79 1 => Self::Running,
80 2 => Self::Closed,
81 _ => unreachable!(),
82 }
83 }
84}
85
86pub struct AudioContextRegistration {
94 context: ConcreteBaseAudioContext,
96 id: AudioNodeId,
98}
99
100impl std::fmt::Debug for AudioContextRegistration {
101 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
102 f.debug_struct("AudioContextRegistration")
103 .field("id", &self.id)
104 .field(
105 "context",
106 &format!("BaseAudioContext@{}", self.context.address()),
107 )
108 .finish()
109 }
110}
111
112impl AudioContextRegistration {
113 #[must_use]
115 pub(crate) fn id(&self) -> AudioNodeId {
116 self.id
117 }
118
119 #[must_use]
121 pub(crate) fn context(&self) -> &ConcreteBaseAudioContext {
122 &self.context
123 }
124
125 pub(crate) fn post_message<M: Any + Send + 'static>(&self, msg: M) {
130 let wrapped = crate::message::ControlMessage::NodeMessage {
131 id: self.id,
132 msg: llq::Node::new(Box::new(msg)),
133 };
134 self.context.send_control_msg(wrapped);
135 }
136}
137
138impl Drop for AudioContextRegistration {
139 fn drop(&mut self) {
140 self.context.mark_node_dropped(self.id);
141 }
142}
143
144#[cfg(test)]
145mod tests {
146 use super::*;
147 use crate::node::AudioNode;
148
149 fn require_send_sync_static<T: Send + Sync + 'static>(_: T) {}
150
151 #[test]
152 fn test_audio_context_registration_traits() {
153 let context = OfflineAudioContext::new(1, 1, 44100.);
154 let registration = context.mock_registration();
155
156 require_send_sync_static(registration);
159 }
160
161 #[test]
162 fn test_offline_audio_context_send_sync() {
163 let context = OfflineAudioContext::new(1, 1, 44100.);
164 require_send_sync_static(context);
165 }
166
167 #[test]
168 fn test_online_audio_context_send_sync() {
169 let options = AudioContextOptions {
170 sink_id: "none".into(),
171 ..AudioContextOptions::default()
172 };
173 let context = AudioContext::new(options);
174 require_send_sync_static(context);
175 }
176
177 #[test]
178 fn test_context_equals() {
179 let context = OfflineAudioContext::new(1, 48000, 96000.);
180 let dest = context.destination();
181 assert!(dest.context() == context.base());
182 }
183}