use crate::{JsJson, dev::JsJsonListDecoder};
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum MediaEventKind {
LoadedMetadata,
DurationChange,
TimeUpdate,
Progress,
Play,
Playing,
Pause,
Waiting,
Seeked,
Ended,
VolumeChange,
Error,
}
impl MediaEventKind {
const ALL: [(&'static str, Self); 12] = [
("loadedmetadata", Self::LoadedMetadata),
("durationchange", Self::DurationChange),
("timeupdate", Self::TimeUpdate),
("progress", Self::Progress),
("play", Self::Play),
("playing", Self::Playing),
("pause", Self::Pause),
("waiting", Self::Waiting),
("seeked", Self::Seeked),
("ended", Self::Ended),
("volumechange", Self::VolumeChange),
("error", Self::Error),
];
fn from_name(name: &str) -> Option<Self> {
Self::ALL
.iter()
.find(|(known, _)| *known == name)
.map(|(_, kind)| *kind)
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct MediaEvent {
pub kind: MediaEventKind,
pub current_time: f64,
pub duration: Option<f64>,
pub paused: bool,
pub ended: bool,
pub muted: bool,
pub volume: f64,
pub buffered: f64,
}
impl MediaEvent {
pub(crate) fn from_driver(data: JsJson) -> Result<Self, String> {
data.map_list(|mut params: JsJsonListDecoder| {
let name = params.get_string("type")?;
let kind = MediaEventKind::from_name(&name)
.ok_or_else(|| format!("type -> unknown media event {name}"))?;
let current_time = params.get_f64("currentTime")?;
let duration = match params.get_any("duration")? {
JsJson::Number(duration) => Some(duration.as_f64()),
JsJson::Null => None,
other => {
return Err(format!(
"duration -> number expected, received {}",
other.typename()
));
}
};
let paused = params.get_bool("paused")?;
let ended = params.get_bool("ended")?;
let muted = params.get_bool("muted")?;
let volume = params.get_f64("volume")?;
let buffered = params.get_f64("buffered")?;
params.expect_no_more()?;
Ok(Self {
kind,
current_time,
duration,
paused,
ended,
muted,
volume,
buffered,
})
})
}
}
impl std::fmt::Display for MediaEvent {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "MediaEvent={:?}", self.kind)
}
}