pub mod audio;
pub mod devices;
pub mod video;
use wasm_bindgen::{JsCast, JsValue};
pub(crate) fn sweep() {
audio::sweep();
video::sweep();
}
pub(crate) fn describe(error: JsValue) -> String {
error
.dyn_ref::<js_sys::Error>()
.map(|error| String::from(error.message()))
.or_else(|| error.as_string())
.unwrap_or_else(|| format!("{error:?}"))
}
pub(crate) fn media_devices() -> Result<web_sys::MediaDevices, String> {
let window = web_sys::window().ok_or("no window")?;
window.navigator().media_devices().map_err(|e| {
format!(
"navigator.mediaDevices is unavailable ({}): this needs https, or localhost",
describe(e)
)
})
}
pub(crate) fn exactly(id: Option<&str>) -> Result<JsValue, String> {
let Some(id) = id else {
return Ok(JsValue::TRUE);
};
let exact = js_sys::Object::new();
js_sys::Reflect::set(&exact, &"exact".into(), &id.into()).map_err(describe)?;
let constraint = js_sys::Object::new();
js_sys::Reflect::set(&constraint, &"deviceId".into(), &exact).map_err(describe)?;
Ok(constraint.into())
}
pub(crate) fn stop_stream(stream: &web_sys::MediaStream) {
for track in stream.get_tracks().iter() {
if let Ok(track) = track.dyn_into::<web_sys::MediaStreamTrack>() {
track.stop();
}
}
}
pub(crate) fn now_ms() -> u64 {
use std::sync::OnceLock;
static START: OnceLock<web_time::Instant> = OnceLock::new();
START
.get_or_init(web_time::Instant::now)
.elapsed()
.as_millis() as u64
}