use super::error::{BuilderError, BuilderResult, DurationExt};
use crate::time::{BreakDuration, SpliceTime};
use crate::types::{SpliceInsert, SpliceInsertComponent, TimeSignal};
use std::time::Duration;
#[derive(Debug)]
pub struct SpliceInsertBuilder {
splice_event_id: Option<u32>,
out_of_network: bool,
program_splice: bool,
splice_immediate: bool,
splice_time: Option<Duration>,
components: Vec<ComponentTiming>,
duration: Option<Duration>,
auto_return: bool,
unique_program_id: u16,
avail_num: u8,
avails_expected: u8,
}
#[derive(Clone, Debug)]
struct ComponentTiming {
component_tag: u8,
splice_time: Option<Duration>,
}
impl SpliceInsertBuilder {
pub fn new(splice_event_id: u32) -> Self {
Self {
splice_event_id: Some(splice_event_id),
out_of_network: true, program_splice: true, splice_immediate: false,
splice_time: None,
components: Vec::new(),
duration: None,
auto_return: true,
unique_program_id: 0,
avail_num: 0,
avails_expected: 0,
}
}
pub fn cancel_event(mut self) -> Self {
self.splice_event_id = None; self
}
pub fn out_of_network(mut self, out: bool) -> Self {
self.out_of_network = out;
self
}
pub fn immediate(mut self) -> Self {
self.splice_immediate = true;
self.splice_time = None;
self
}
pub fn at_pts(mut self, pts_time: Duration) -> BuilderResult<Self> {
self.splice_immediate = false;
self.splice_time = Some(pts_time);
Ok(self)
}
pub fn component_splice(
mut self,
components: Vec<(u8, Option<Duration>)>,
) -> BuilderResult<Self> {
if components.len() > 255 {
return Err(BuilderError::InvalidComponentCount {
max: 255,
actual: components.len(),
});
}
self.program_splice = false;
self.components = components
.into_iter()
.map(|(tag, time)| ComponentTiming {
component_tag: tag,
splice_time: time,
})
.collect();
Ok(self)
}
pub fn duration(mut self, duration: Duration) -> Self {
self.duration = Some(duration);
self
}
pub fn auto_return(mut self, auto_return: bool) -> Self {
self.auto_return = auto_return;
self
}
pub fn unique_program_id(mut self, id: u16) -> Self {
self.unique_program_id = id;
self
}
pub fn avail(mut self, num: u8, expected: u8) -> Self {
self.avail_num = num;
self.avails_expected = expected;
self
}
pub fn build(self) -> BuilderResult<SpliceInsert> {
let (splice_event_id, cancel) = match self.splice_event_id {
Some(id) => (id, 0),
None => (0, 1), };
let splice_time = if self.program_splice && !self.splice_immediate {
let pts = match self.splice_time {
Some(duration) => {
let ticks = duration.to_pts_ticks();
if ticks > 0x1_FFFF_FFFF {
return Err(BuilderError::DurationTooLarge {
field: "splice_time",
duration,
});
}
Some(ticks)
}
None => None,
};
Some(SpliceTime {
time_specified_flag: 1,
pts_time: pts,
})
} else {
None
};
let mut components = Vec::new();
if !self.program_splice {
for c in self.components {
let splice_time = if !self.splice_immediate {
let pts = match c.splice_time {
Some(duration) => {
let ticks = duration.to_pts_ticks();
if ticks > 0x1_FFFF_FFFF {
return Err(BuilderError::DurationTooLarge {
field: "component_splice_time",
duration,
});
}
Some(ticks)
}
None => None,
};
Some(SpliceTime {
time_specified_flag: 1,
pts_time: pts,
})
} else {
None
};
components.push(SpliceInsertComponent {
component_tag: c.component_tag,
splice_time,
});
}
}
let break_duration = match self.duration {
Some(duration) => {
let ticks = duration.to_pts_ticks();
if ticks > 0x1_FFFF_FFFF {
return Err(BuilderError::DurationTooLarge {
field: "duration",
duration,
});
}
Some(BreakDuration {
auto_return: self.auto_return as u8,
reserved: 0x3F, duration: ticks,
})
}
None => None,
};
Ok(SpliceInsert {
splice_event_id,
splice_event_cancel_indicator: cancel,
reserved: 0x7F, out_of_network_indicator: self.out_of_network as u8,
program_splice_flag: self.program_splice as u8,
duration_flag: self.duration.is_some() as u8,
splice_immediate_flag: self.splice_immediate as u8,
reserved2: 0x0F, splice_time,
component_count: components.len() as u8,
components,
break_duration,
unique_program_id: self.unique_program_id,
avail_num: self.avail_num,
avails_expected: self.avails_expected,
})
}
}
#[derive(Debug)]
pub struct TimeSignalBuilder {
pts_time: Option<Duration>,
}
impl TimeSignalBuilder {
pub fn new() -> Self {
Self { pts_time: None }
}
pub fn immediate(self) -> Self {
self }
pub fn at_pts(mut self, pts_time: Duration) -> BuilderResult<Self> {
self.pts_time = Some(pts_time);
Ok(self)
}
pub fn build(self) -> BuilderResult<TimeSignal> {
let pts_time = match self.pts_time {
Some(duration) => {
let ticks = duration.to_pts_ticks();
if ticks > 0x1_FFFF_FFFF {
return Err(BuilderError::DurationTooLarge {
field: "pts_time",
duration,
});
}
Some(ticks)
}
None => None,
};
Ok(TimeSignal {
splice_time: SpliceTime {
time_specified_flag: pts_time.is_some() as u8,
pts_time,
},
})
}
}
impl Default for TimeSignalBuilder {
fn default() -> Self {
Self::new()
}
}