use std::sync::Arc;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum RungStatus {
Pending,
Running,
Finalizing,
Completed,
Failed,
}
#[derive(Debug, Clone)]
pub struct RungProgress {
pub rung_index: usize,
pub label: String,
pub width: u32,
pub height: u32,
pub status: RungStatus,
pub percent: f32,
pub frames_done: u64,
pub frames_total: Option<u64>,
pub segments_written: u32,
pub bytes_out: u64,
pub message: Option<String>,
}
impl RungProgress {
pub fn pending(rung_index: usize, label: impl Into<String>, width: u32, height: u32) -> Self {
Self {
rung_index,
label: label.into(),
width,
height,
status: RungStatus::Pending,
percent: 0.0,
frames_done: 0,
frames_total: None,
segments_written: 0,
bytes_out: 0,
message: None,
}
}
}
#[derive(Debug, Clone)]
pub enum JobEvent {
Started { rungs: usize },
Probed {
codec: String,
width: u32,
height: u32,
frame_rate: f64,
audio_codec: Option<String>,
},
Finished {
rungs_completed: usize,
rungs_failed: usize,
},
}
pub trait ProgressSink: Send + Sync {
fn on_rung(&self, update: RungProgress);
fn on_event(&self, _event: JobEvent) {}
}
pub struct NullSink;
impl ProgressSink for NullSink {
fn on_rung(&self, _update: RungProgress) {}
}
pub struct FnSink<F>(F);
impl<F: Fn(RungProgress) + Send + Sync> ProgressSink for FnSink<F> {
fn on_rung(&self, update: RungProgress) {
(self.0)(update)
}
}
pub fn fn_sink<F: Fn(RungProgress) + Send + Sync>(f: F) -> FnSink<F> {
FnSink(f)
}
pub struct ChannelSink {
tx: tokio::sync::mpsc::Sender<RungProgress>,
}
impl ChannelSink {
pub fn new(tx: tokio::sync::mpsc::Sender<RungProgress>) -> Self {
Self { tx }
}
}
impl ProgressSink for ChannelSink {
fn on_rung(&self, update: RungProgress) {
let _ = self.tx.try_send(update);
}
}
pub fn channel_sink(tx: tokio::sync::mpsc::Sender<RungProgress>) -> Arc<dyn ProgressSink> {
Arc::new(ChannelSink::new(tx))
}