use core::fmt;
use std::net::Ipv4Addr;
use crate::wire::{DeviceUid, EdidProfile, RcAction, RcKey};
#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub struct SetRouteRequest {
pub serial: String,
pub sink_bay: u16,
pub source_bay: u16,
pub no_power_on: bool,
pub audio_only: bool,
}
impl fmt::Display for SetRouteRequest {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"set route on {}: sink={} source={}",
self.serial, self.sink_bay, self.source_bay
)
}
}
#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub struct EdidRecord {
pub output: bool,
pub data: Vec<u8>,
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub struct EdidRequest {
pub target: DeviceUid,
pub output: bool,
}
#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub struct BayNameChange {
pub target: DeviceUid,
pub port: u16,
pub name: String,
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub struct EdidProfileChange {
pub target: DeviceUid,
pub profile: EdidProfile,
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub struct FactoryResetRequest {
pub all: bool,
pub target: Option<DeviceUid>,
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub struct RebootRequest {
pub target: DeviceUid,
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub struct V2ipTilingConfig {
pub target: DeviceUid,
pub pos_x: u16,
pub pos_y: u16,
pub width: u16,
pub height: u16,
}
impl fmt::Display for V2ipTilingConfig {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"tiling x={} y={} {}x{}",
self.pos_x, self.pos_y, self.width, self.height
)
}
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub struct V2ipPowerSaveRequest {
pub target: Option<DeviceUid>,
pub enabled: bool,
}
#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub struct RcSettings {
pub target: DeviceUid,
pub rc_target: u8,
pub ip: Option<Ipv4Addr>,
pub cec_enabled: bool,
pub cec_auto_on: bool,
pub forward_rc: bool,
pub forward_ir: bool,
pub rc_status: u8,
pub status_name: String,
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub struct IrMeta {
pub timer_resolution: u16,
pub frequency: u16,
pub nb_timings: u16,
pub repeat_offset: u16,
pub status: u8,
}
#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub struct IrCapture {
pub port: u16,
pub timestamp: u32,
pub last_change: u32,
pub meta: IrMeta,
pub timings: Vec<u8>,
}
#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub struct IrTransmitRequest {
pub target: DeviceUid,
pub local_mode: u8,
pub local_bay: u8,
pub timestamp: u32,
pub meta: IrMeta,
pub timings: Vec<u8>,
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub struct KeyTransmitRequest {
pub target: DeviceUid,
pub local_bay: u16,
pub key: RcKey,
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub struct ActionTransmitRequest {
pub target: DeviceUid,
pub local_bay: u16,
pub action: RcAction,
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub struct AudioClip {
pub port: u16,
pub clip: u8,
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub struct V2ipBlacklistChange {
pub target: DeviceUid,
pub registered: bool,
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct VideoWallOp(u8);
impl VideoWallOp {
pub const PREVIEW: Self = Self(0);
pub const STORE: Self = Self(1);
pub const REVERT: Self = Self(2);
pub const fn from_wire(value: u8) -> Self {
Self(value)
}
pub const fn to_wire(self) -> u8 {
self.0
}
}
impl fmt::Display for VideoWallOp {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(match *self {
Self::PREVIEW => "preview",
Self::STORE => "store",
Self::REVERT => "revert",
_ => "unknown",
})
}
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub struct VideoWallWindow {
pub pos_x: u16,
pub pos_y: u16,
pub width: u16,
pub height: u16,
pub raster_w: u16,
pub raster_h: u16,
}
pub const VIDEO_WALL_CLEARED: VideoWallWindow = VideoWallWindow {
pos_x: 0,
pos_y: 0,
width: 0,
height: 0,
raster_w: 0,
raster_h: 0,
};
pub const VIDEO_WALL_POS_ALIGN: u16 = 64;
pub const VIDEO_WALL_WIDTH_ALIGN: u16 = 4;
pub const VIDEO_WALL_MIN_SIZE: u16 = 64;
impl VideoWallWindow {
pub const fn is_cleared(&self) -> bool {
self.width == 0 || self.height == 0
}
pub fn validate(&self) -> Result<(), &'static str> {
if self.is_cleared() {
return Ok(());
}
if self.pos_x % VIDEO_WALL_POS_ALIGN != 0 {
return Err("a video wall window's horizontal origin must be a multiple of 64");
}
if self.width % VIDEO_WALL_WIDTH_ALIGN != 0 {
return Err("a video wall window's width must be a multiple of 4");
}
if self.width < VIDEO_WALL_MIN_SIZE || self.height < VIDEO_WALL_MIN_SIZE {
return Err("neither side of a video wall window may be smaller than 64");
}
if self.raster_w == 0 || self.raster_h == 0 {
return Ok(());
}
if u32::from(self.pos_x) + u32::from(self.width) > u32::from(self.raster_w)
|| u32::from(self.pos_y) + u32::from(self.height) > u32::from(self.raster_h)
{
return Err("a video wall window must fit inside the raster it names");
}
Ok(())
}
}
impl fmt::Display for VideoWallWindow {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if self.is_cleared() {
return f.write_str("cleared");
}
write!(
f,
"{}x{}+{}+{} of {}x{}",
self.width, self.height, self.pos_x, self.pos_y, self.raster_w, self.raster_h
)
}
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub struct VideoWallCommand {
pub target: DeviceUid,
pub pos_x: u16,
pub pos_y: u16,
pub width: u16,
pub height: u16,
pub raster_w: u16,
pub raster_h: u16,
pub op: VideoWallOp,
}
impl VideoWallCommand {
pub fn has_window(&self) -> bool {
self.op != VideoWallOp::REVERT
}
pub fn is_cleared(&self) -> bool {
self.has_window() && (self.width == 0 || self.height == 0)
}
}
impl fmt::Display for VideoWallCommand {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if !self.has_window() {
return f.write_str("video wall revert");
}
if self.is_cleared() {
return write!(f, "video wall {}: clear", self.op);
}
write!(
f,
"video wall {}: {}x{}+{}+{} of {}x{}",
self.op, self.width, self.height, self.pos_x, self.pos_y, self.raster_w, self.raster_h
)
}
}
#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub struct MultiviewerCommand {
pub target: DeviceUid,
pub op: u8,
pub params: Vec<u8>,
}
impl fmt::Display for MultiviewerCommand {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"multiviewer command {} for {} ({} param bytes)",
self.op,
self.target,
self.params.len()
)
}
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub struct AudioChangeSource {
pub source_uid: DeviceUid,
pub source_id: u16,
pub target_uid: DeviceUid,
pub target_id: u16,
}
impl fmt::Display for AudioChangeSource {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"audio source change {}:{} -> {}:{}",
self.source_uid, self.source_id, self.target_uid, self.target_id
)
}
}