wip: _top

This commit is contained in:
Baud 2024-03-18 19:23:28 +00:00
parent 493bf7a6e8
commit d2f41821c0
12 changed files with 158 additions and 12 deletions

View File

@ -103,6 +103,8 @@ pub struct AtemSocket {
socket: Option<UdpSocket>,
address: SocketAddr,
protocol_version: ProtocolVersion,
last_received_at: SystemTime,
last_received_packed_id: u16,
in_flight: Vec<InFlightPacket>,
@ -159,6 +161,8 @@ impl AtemSocket {
socket: None,
address: "0.0.0.0:0".parse().unwrap(),
protocol_version: ProtocolVersion::V7_2,
last_received_at: SystemTime::now(),
last_received_packed_id: 0,
in_flight: vec![],
@ -532,7 +536,7 @@ impl AtemSocket {
}
fn on_commands_received(&mut self, payload: &[u8]) {
let commands = deserialize_commands(payload);
let commands = deserialize_commands(payload, &self.protocol_version);
let _ = self
.atem_event_tx

View File

@ -8,7 +8,8 @@ pub trait DeserializedCommand: Send + Sync + Debug {
}
pub trait CommandDeserializer: Send + Sync {
fn deserialize(&self, buffer: &[u8]) -> Arc<dyn DeserializedCommand>;
fn deserialize(&self, buffer: &[u8], version: &ProtocolVersion)
-> Arc<dyn DeserializedCommand>;
}
pub trait SerializableCommand: Send + Sync {

View File

@ -1,2 +1,3 @@
pub mod product_identifier;
pub mod topology;
pub mod version;

View File

@ -2,7 +2,7 @@ use std::{ffi::CString, sync::Arc};
use crate::{
commands::command_base::{CommandDeserializer, DeserializedCommand},
enums::Model,
enums::{Model, ProtocolVersion},
};
pub const DESERIALIZE_PRODUCT_IDENTIFIER_RAW_NAME: &str = "_pin";
@ -43,7 +43,11 @@ impl DeserializedCommand for ProductIdentifierCommand {
pub struct ProductIdentifierCommandDeserializer {}
impl CommandDeserializer for ProductIdentifierCommandDeserializer {
fn deserialize(&self, buffer: &[u8]) -> std::sync::Arc<dyn DeserializedCommand> {
fn deserialize(
&self,
buffer: &[u8],
version: &ProtocolVersion,
) -> std::sync::Arc<dyn DeserializedCommand> {
let null_byte_index = buffer
.iter()
.position(|byte| *byte == b'\0')

View File

@ -0,0 +1,91 @@
use std::sync::Arc;
use crate::{
commands::command_base::{CommandDeserializer, DeserializedCommand},
enums::ProtocolVersion,
};
pub const DESERIALIZE_TOPOLOGY_RAW_NAME: &str = "_top";
#[derive(Debug)]
pub struct TopologyCommand {
mix_effects: u8,
sources: u8,
auxilliaries: u8,
mix_minus_outputs: u8,
media_players: u8,
multiviewers: Option<u8>,
serial_ports: u8,
max_hyperdecks: u8,
dves: u8,
stingers: u8,
super_sources: u8,
talkback_channels: u8,
downstream_keyers: u8,
camera_control: bool,
advanced_chroma_keyers: bool,
only_configurable_outputs: bool,
}
impl DeserializedCommand for TopologyCommand {
fn raw_name(&self) -> &'static str {
todo!()
}
fn apply_to_state(&self, state: &mut crate::state::AtemState) {
todo!()
}
}
pub struct TopologyCommandDeserializer {}
impl CommandDeserializer for TopologyCommandDeserializer {
fn deserialize(
&self,
buffer: &[u8],
version: &ProtocolVersion,
) -> std::sync::Arc<dyn crate::commands::command_base::DeserializedCommand> {
let v230offset = if *version > ProtocolVersion::V8_0_1 {
1
} else {
0
};
let multiviewers = if v230offset > 0 {
Some(buffer[6])
} else {
None
};
let advanced_chroma_keyers = if buffer.len() > 20 {
buffer[21 + v230offset] == 1
} else {
false
};
let only_configurable_outputs = if buffer.len() > 20 {
buffer[22 + v230offset] == 1
} else {
false
};
Arc::new(TopologyCommand {
mix_effects: buffer[0],
sources: buffer[1],
downstream_keyers: buffer[2],
auxilliaries: buffer[3],
mix_minus_outputs: buffer[4],
media_players: buffer[5],
multiviewers,
serial_ports: buffer[6 + v230offset],
max_hyperdecks: buffer[7 + v230offset],
dves: buffer[8 + v230offset],
stingers: buffer[9 + v230offset],
super_sources: buffer[10 + v230offset],
talkback_channels: buffer[12 + v230offset],
camera_control: buffer[17 + v230offset] == 1,
advanced_chroma_keyers,
only_configurable_outputs,
})
}
}

View File

@ -26,7 +26,11 @@ impl DeserializedCommand for VersionCommand {
pub struct VersionCommandDeserializer {}
impl CommandDeserializer for VersionCommandDeserializer {
fn deserialize(&self, buffer: &[u8]) -> std::sync::Arc<dyn DeserializedCommand> {
fn deserialize(
&self,
buffer: &[u8],
version: &ProtocolVersion,
) -> std::sync::Arc<dyn DeserializedCommand> {
let version = u32::from_be_bytes([buffer[0], buffer[1], buffer[2], buffer[3]]);
let version: ProtocolVersion = version.try_into().expect("Invalid protocol version");

View File

@ -1,5 +1,7 @@
use std::sync::Arc;
use crate::enums::ProtocolVersion;
use super::command_base::{CommandDeserializer, DeserializedCommand};
pub const DESERIALIZE_INIT_COMPLETE_RAW_NAME: &str = "InCm";
@ -19,7 +21,11 @@ impl DeserializedCommand for InitComplete {
pub struct InitCompleteDeserializer {}
impl CommandDeserializer for InitCompleteDeserializer {
fn deserialize(&self, _buffer: &[u8]) -> std::sync::Arc<dyn DeserializedCommand> {
fn deserialize(
&self,
_buffer: &[u8],
version: &ProtocolVersion,
) -> std::sync::Arc<dyn DeserializedCommand> {
Arc::new(InitComplete {})
}
}

View File

@ -4,6 +4,7 @@ use crate::{
commands::command_base::{
BasicWritableCommand, CommandDeserializer, DeserializedCommand, SerializableCommand,
},
enums::ProtocolVersion,
state::util::get_mix_effect,
};
@ -58,7 +59,11 @@ impl DeserializedCommand for ProgramInput {
pub struct ProgramInputDeserializer {}
impl CommandDeserializer for ProgramInputDeserializer {
fn deserialize(&self, buffer: &[u8]) -> Arc<dyn DeserializedCommand> {
fn deserialize(
&self,
buffer: &[u8],
version: &ProtocolVersion,
) -> Arc<dyn DeserializedCommand> {
let mix_effect = buffer[0];
let source = u16::from_be_bytes([buffer[2], buffer[3]]);

View File

@ -1,5 +1,7 @@
use std::{collections::VecDeque, sync::Arc};
use crate::enums::ProtocolVersion;
use super::{
command_base::{CommandDeserializer, DeserializedCommand},
device_profile::{
@ -14,7 +16,10 @@ use super::{
time::{TimeDeserializer, DESERIALIZE_TIME_RAW_NAME},
};
pub fn deserialize_commands(payload: &[u8]) -> VecDeque<Arc<dyn DeserializedCommand>> {
pub fn deserialize_commands(
payload: &[u8],
version: &ProtocolVersion,
) -> VecDeque<Arc<dyn DeserializedCommand>> {
let mut parsed_commands = VecDeque::new();
let mut head = 0;
@ -31,13 +36,14 @@ pub fn deserialize_commands(payload: &[u8]) -> VecDeque<Arc<dyn DeserializedComm
log::debug!("Received command {} with length {}", name, length);
if let Some(deserializer) = command_deserializer_from_string(name.as_str()) {
let deserialized_command = deserializer.deserialize(&payload[head + 8..head + length]);
let deserialized_command =
deserializer.deserialize(&payload[head + 8..head + length], version);
log::debug!("Received {:?}", deserialized_command);
parsed_commands.push_back(deserialized_command);
} else {
log::warn!("Received command {name} for which there is no deserializer.");
// TODO: Remove!
todo!("Write deserializer for {name}.");
// todo!("Write deserializer for {name}.");
}
head += length;

View File

@ -1,5 +1,7 @@
use std::{collections::HashMap, sync::Arc};
use crate::enums::ProtocolVersion;
use super::command_base::{CommandDeserializer, DeserializedCommand};
pub const DESERIALIZE_TALLY_BY_SOURCE_RAW_NAME: &str = "TlSr";
@ -29,7 +31,11 @@ impl DeserializedCommand for TallyBySource {
pub struct TallyBySourceDeserializer {}
impl CommandDeserializer for TallyBySourceDeserializer {
fn deserialize(&self, buffer: &[u8]) -> Arc<dyn DeserializedCommand> {
fn deserialize(
&self,
buffer: &[u8],
version: &ProtocolVersion,
) -> Arc<dyn DeserializedCommand> {
let source_count = u16::from_be_bytes([buffer[0], buffer[1]]) as usize;
log::debug!("{:?}", buffer);

View File

@ -1,5 +1,7 @@
use std::sync::Arc;
use crate::enums::ProtocolVersion;
use super::command_base::{CommandDeserializer, DeserializedCommand};
pub const DESERIALIZE_TIME_RAW_NAME: &str = "Time";
@ -33,6 +35,7 @@ impl CommandDeserializer for TimeDeserializer {
fn deserialize(
&self,
buffer: &[u8],
version: &ProtocolVersion,
) -> std::sync::Arc<dyn super::command_base::DeserializedCommand> {
let info = TimeInfo {
hour: buffer[0],

View File

@ -1,3 +1,5 @@
use std::fmt::Display;
#[derive(Debug, Clone, Default, PartialEq)]
pub enum Model {
#[default]
@ -71,7 +73,7 @@ impl From<u8> for Model {
}
}
#[derive(Debug, Default, Clone, Copy, PartialEq)]
#[derive(Debug, Default, Clone, Copy, PartialEq, PartialOrd)]
pub enum ProtocolVersion {
#[default]
Unknown = 0,
@ -98,6 +100,19 @@ impl TryFrom<u32> for ProtocolVersion {
}
}
impl Display for ProtocolVersion {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ProtocolVersion::Unknown => write!(f, "Unknown"),
ProtocolVersion::V7_2 => write!(f, "v7.2"),
ProtocolVersion::V7_5_2 => write!(f, "v7.5.2"),
ProtocolVersion::V8_0 => write!(f, "v8.0"),
ProtocolVersion::V8_0_1 => write!(f, "v8.0.1"),
ProtocolVersion::V8_1_1 => write!(f, "v8.1.1"),
}
}
}
#[derive(Clone, PartialEq)]
pub enum TransitionStyle {
MIX = 0x00,