oximedia_clips/proxy/
link.rs1use crate::clip::ClipId;
4use crate::error::{ClipError, ClipResult};
5use serde::{Deserialize, Serialize};
6use std::path::PathBuf;
7use uuid::Uuid;
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
11pub struct ProxyLinkId(Uuid);
12
13impl ProxyLinkId {
14 #[must_use]
16 pub fn new() -> Self {
17 Self(Uuid::new_v4())
18 }
19
20 #[must_use]
22 pub const fn from_uuid(uuid: Uuid) -> Self {
23 Self(uuid)
24 }
25
26 #[must_use]
28 pub const fn as_uuid(&self) -> &Uuid {
29 &self.0
30 }
31}
32
33impl Default for ProxyLinkId {
34 fn default() -> Self {
35 Self::new()
36 }
37}
38
39#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
41pub enum ProxyQuality {
42 Low,
44 Medium,
46 High,
48 Custom,
50}
51
52impl ProxyQuality {
53 #[must_use]
55 pub const fn all() -> [Self; 4] {
56 [Self::Low, Self::Medium, Self::High, Self::Custom]
57 }
58
59 pub fn parse(s: &str) -> ClipResult<Self> {
65 match s.to_lowercase().as_str() {
66 "low" => Ok(Self::Low),
67 "medium" => Ok(Self::Medium),
68 "high" => Ok(Self::High),
69 "custom" => Ok(Self::Custom),
70 _ => Err(ClipError::InvalidProxyQuality(s.to_string())),
71 }
72 }
73}
74
75impl std::fmt::Display for ProxyQuality {
76 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
77 match self {
78 Self::Low => write!(f, "Low"),
79 Self::Medium => write!(f, "Medium"),
80 Self::High => write!(f, "High"),
81 Self::Custom => write!(f, "Custom"),
82 }
83 }
84}
85
86#[derive(Debug, Clone, Serialize, Deserialize)]
88pub struct ProxyLink {
89 pub id: ProxyLinkId,
91
92 pub clip_id: ClipId,
94
95 pub proxy_path: PathBuf,
97
98 pub quality: ProxyQuality,
100
101 pub resolution: Option<String>,
103
104 pub bitrate: Option<u32>,
106
107 pub codec: Option<String>,
109}
110
111impl ProxyLink {
112 #[must_use]
114 pub fn new(clip_id: ClipId, proxy_path: PathBuf, quality: ProxyQuality) -> Self {
115 Self {
116 id: ProxyLinkId::new(),
117 clip_id,
118 proxy_path,
119 quality,
120 resolution: None,
121 bitrate: None,
122 codec: None,
123 }
124 }
125
126 pub fn set_resolution(&mut self, resolution: impl Into<String>) {
128 self.resolution = Some(resolution.into());
129 }
130
131 pub fn set_bitrate(&mut self, bitrate: u32) {
133 self.bitrate = Some(bitrate);
134 }
135
136 pub fn set_codec(&mut self, codec: impl Into<String>) {
138 self.codec = Some(codec.into());
139 }
140
141 #[must_use]
143 pub fn proxy_exists(&self) -> bool {
144 self.proxy_path.exists()
145 }
146}
147
148#[cfg(test)]
149mod tests {
150 use super::*;
151
152 #[test]
153 fn test_proxy_quality() {
154 assert_eq!(
155 ProxyQuality::parse("low").expect("parse should succeed"),
156 ProxyQuality::Low
157 );
158 assert_eq!(
159 ProxyQuality::parse("medium").expect("parse should succeed"),
160 ProxyQuality::Medium
161 );
162 assert!(ProxyQuality::parse("invalid").is_err());
163 }
164
165 #[test]
166 fn test_proxy_link() {
167 let clip_id = ClipId::new();
168 let proxy_path = PathBuf::from("/proxy/test.mov");
169 let mut link = ProxyLink::new(clip_id, proxy_path, ProxyQuality::Medium);
170
171 link.set_resolution("1920x1080");
172 link.set_bitrate(10_000);
173 link.set_codec("ProRes");
174
175 assert_eq!(link.resolution, Some("1920x1080".to_string()));
176 assert_eq!(link.bitrate, Some(10_000));
177 }
178}