use crate::clip::ClipId;
use crate::error::{ClipError, ClipResult};
use serde::{Deserialize, Serialize};
use std::path::PathBuf;
use uuid::Uuid;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct ProxyLinkId(Uuid);
impl ProxyLinkId {
#[must_use]
pub fn new() -> Self {
Self(Uuid::new_v4())
}
#[must_use]
pub const fn from_uuid(uuid: Uuid) -> Self {
Self(uuid)
}
#[must_use]
pub const fn as_uuid(&self) -> &Uuid {
&self.0
}
}
impl Default for ProxyLinkId {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum ProxyQuality {
Low,
Medium,
High,
Custom,
}
impl ProxyQuality {
#[must_use]
pub const fn all() -> [Self; 4] {
[Self::Low, Self::Medium, Self::High, Self::Custom]
}
pub fn parse(s: &str) -> ClipResult<Self> {
match s.to_lowercase().as_str() {
"low" => Ok(Self::Low),
"medium" => Ok(Self::Medium),
"high" => Ok(Self::High),
"custom" => Ok(Self::Custom),
_ => Err(ClipError::InvalidProxyQuality(s.to_string())),
}
}
}
impl std::fmt::Display for ProxyQuality {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Low => write!(f, "Low"),
Self::Medium => write!(f, "Medium"),
Self::High => write!(f, "High"),
Self::Custom => write!(f, "Custom"),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ProxyLink {
pub id: ProxyLinkId,
pub clip_id: ClipId,
pub proxy_path: PathBuf,
pub quality: ProxyQuality,
pub resolution: Option<String>,
pub bitrate: Option<u32>,
pub codec: Option<String>,
}
impl ProxyLink {
#[must_use]
pub fn new(clip_id: ClipId, proxy_path: PathBuf, quality: ProxyQuality) -> Self {
Self {
id: ProxyLinkId::new(),
clip_id,
proxy_path,
quality,
resolution: None,
bitrate: None,
codec: None,
}
}
pub fn set_resolution(&mut self, resolution: impl Into<String>) {
self.resolution = Some(resolution.into());
}
pub fn set_bitrate(&mut self, bitrate: u32) {
self.bitrate = Some(bitrate);
}
pub fn set_codec(&mut self, codec: impl Into<String>) {
self.codec = Some(codec.into());
}
#[must_use]
pub fn proxy_exists(&self) -> bool {
self.proxy_path.exists()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_proxy_quality() {
assert_eq!(
ProxyQuality::parse("low").expect("parse should succeed"),
ProxyQuality::Low
);
assert_eq!(
ProxyQuality::parse("medium").expect("parse should succeed"),
ProxyQuality::Medium
);
assert!(ProxyQuality::parse("invalid").is_err());
}
#[test]
fn test_proxy_link() {
let clip_id = ClipId::new();
let proxy_path = PathBuf::from("/proxy/test.mov");
let mut link = ProxyLink::new(clip_id, proxy_path, ProxyQuality::Medium);
link.set_resolution("1920x1080");
link.set_bitrate(10_000);
link.set_codec("ProRes");
assert_eq!(link.resolution, Some("1920x1080".to_string()));
assert_eq!(link.bitrate, Some(10_000));
}
}