use js_sys::Reflect;
use std::sync::OnceLock;
use wasm_bindgen::JsValue;
use web_sys::window;
static IS_IOS: OnceLock<bool> = OnceLock::new();
static SUPPORTS_WEBCODECS: OnceLock<bool> = OnceLock::new();
pub fn is_ios() -> bool {
*IS_IOS.get_or_init(|| {
if let Some(window) = window() {
if let Ok(ua) = window.navigator().user_agent() {
let ua_lower = ua.to_lowercase();
let is_ios = ua_lower.contains("iphone")
|| ua_lower.contains("ipad")
|| ua_lower.contains("ipod")
|| (ua_lower.contains("safari") && !ua_lower.contains("chrome"));
log::info!("Platform detection: UA='{ua}', is_ios={is_ios}");
return is_ios;
}
}
false
})
}
pub fn supports_webcodecs_audio() -> bool {
*SUPPORTS_WEBCODECS.get_or_init(|| {
if let Some(window) = window() {
let global = JsValue::from(window);
if let Ok(true) = Reflect::has(&global, &JsValue::from_str("AudioDecoder")) {
match Reflect::get(&global, &JsValue::from_str("AudioDecoder")) {
Ok(constructor) if !constructor.is_undefined() && !constructor.is_null() => {
log::info!("WebCodecs AudioDecoder available");
return true;
}
_ => {}
}
}
}
log::info!("WebCodecs AudioDecoder not available");
false
})
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum AudioBackend {
WebCodecs,
JsLibrary,
}
pub fn detect_audio_backend() -> AudioBackend {
if is_ios() {
log::info!("Selected audio backend: JsLibrary (iOS/Safari)");
return AudioBackend::JsLibrary;
}
if supports_webcodecs_audio() {
log::info!("Selected audio backend: WebCodecs (hardware-accelerated)");
return AudioBackend::WebCodecs;
}
log::info!("Selected audio backend: JsLibrary (fallback)");
AudioBackend::JsLibrary
}