use crate::component::Stream;
use crate::si::{Event, Service};
pub fn or_unknown(value: &str) -> &str {
if value.is_empty() { "(unknown)" } else { value }
}
pub fn print_service(service: &Service, indent: usize) {
let pad = " ".repeat(indent);
print!("{pad}{:#06X}: {}", service.id, or_unknown(&service.name));
if let Some(service_type) = service.service_type {
print!(" (type {service_type:#04X})");
}
println!();
if !service.provider.is_empty() {
println!("{pad} Provider: {}", service.provider);
}
}
pub fn print_event(event: &Event, indent: usize, verbose: bool) {
let pad = " ".repeat(indent);
let time = match (event.start_time, event.duration) {
(Some(start), Some(duration)) => format!(
"{} - {} ({} min)",
start.format("%Y-%m-%d %H:%M"),
(start + duration).format("%H:%M"),
duration.num_minutes()
),
(Some(start), None) => format!("{} -", start.format("%Y-%m-%d %H:%M")),
(None, _) => "(time undecided)".to_owned(),
};
println!(
"{pad}{time} {:#06X} {}",
event.id,
or_unknown(&event.name)
);
if !event.text.is_empty() {
for line in event.text.lines() {
println!("{pad} {line}");
}
}
if !verbose {
return;
}
for genre in &event.genres {
println!("{pad} Genre: {genre}");
}
let access = if event.scrambled { "scrambled" } else { "free" };
println!("{pad} Access: {access}");
for (description, item) in &event.details {
println!("{pad} {}:", or_unknown(description));
for line in item.lines() {
println!("{pad} {line}");
}
}
}
pub fn parse_id(value: &str) -> Result<u16, std::num::ParseIntError> {
match value
.strip_prefix("0x")
.or_else(|| value.strip_prefix("0X"))
{
Some(hex) => u16::from_str_radix(hex, 16),
None => value.parse(),
}
}
pub fn print_stream(stream: &Stream, details: &[String], indent: usize) {
let pad = " ".repeat(indent);
let tag = stream
.component_tag
.map(|tag| format!("[{tag:#04X}]"))
.unwrap_or_default();
let details: String = details.iter().map(|detail| format!(", {detail}")).collect();
println!(
"{pad}Stream {:#06X}{tag}: {}: {}{details}",
stream.id, stream.kind, stream.codec
);
}