use std::any::Any;
use std::sync::{Arc, OnceLock};
use bytes::Bytes;
use iroh::endpoint::Connection;
use iroh::{Endpoint, EndpointAddr};
use tokio::sync::mpsc;
use super::share::ShareInput;
use super::stats::MediaStats;
pub struct LinkConn {
pub to_web: mpsc::Sender<Bytes>,
pub from_web: mpsc::Receiver<Bytes>,
}
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum AwakeLevel {
System,
Display,
}
pub struct AudioStart {
pub volume: f32,
pub share_volume: f32,
pub stats: Option<Arc<MediaStats>>,
pub share: Arc<ShareInput>,
}
pub trait CallAudio: Send {
fn stats(&self) -> Arc<MediaStats>;
fn set_muted(&self, on: bool);
fn set_volume(&self, volume: f32);
fn set_share_volume(&self, volume: f32);
}
#[cfg_attr(not(target_arch = "wasm32"), async_trait::async_trait)]
#[cfg_attr(target_arch = "wasm32", async_trait::async_trait(?Send))]
pub trait CallPlatform: Send + Sync + 'static {
async fn endpoint(&self) -> Result<Endpoint, String>;
async fn local_addr(&self) -> Result<String, String>;
fn decode_addr(&self, addr: &str) -> Option<EndpointAddr>;
async fn start_audio(&self, conn: Connection, start: AudioStart) -> Result<Box<dyn CallAudio>, String>;
fn set_video_taker(&self, taker: Option<mpsc::Sender<LinkConn>>);
fn hold_awake(&self, _level: AwakeLevel) -> Option<Box<dyn Any + Send>> {
None
}
fn ended(&self) {}
fn share_audio_native(&self) -> bool {
false
}
async fn start_share_audio(&self, _share: Arc<ShareInput>) -> Result<(), String> {
Err("Not available on this platform".into())
}
async fn stop_share_audio(&self) {}
fn share_audio_permitted(&self) -> bool {
true
}
}
static PLATFORM: OnceLock<Arc<dyn CallPlatform>> = OnceLock::new();
pub fn install(platform: Arc<dyn CallPlatform>) {
let _ = PLATFORM.set(platform);
}
pub(crate) fn get() -> Result<Arc<dyn CallPlatform>, String> {
PLATFORM.get().cloned().ok_or_else(|| "Calls are not available".to_string())
}