Compare commits

...

2 Commits

Author SHA1 Message Date
Baud c30913f823 feat: Deserializing commands 2024-02-24 17:01:28 +00:00
Baud c80d7643ca feat: Program Input deserialization 2024-02-23 11:40:57 +00:00
5 changed files with 67 additions and 57 deletions

View File

@ -346,7 +346,7 @@ impl AtemSocketInner {
self.send_or_queue_ack().await; self.send_or_queue_ack().await;
if length > 12 { if length > 12 {
self.on_command_received(&packet[12..]); self.on_commands_received(&packet[12..]);
} }
} else if self } else if self
.is_packet_covered_by_ack(self.last_received_packed_id, remote_packet_id) .is_packet_covered_by_ack(self.last_received_packed_id, remote_packet_id)
@ -464,7 +464,7 @@ impl AtemSocketInner {
} }
} }
fn on_command_received(&mut self, payload: &[u8]) { fn on_commands_received(&mut self, payload: &[u8]) {
let commands = deserialize_commands(payload); let commands = deserialize_commands(payload);
} }

View File

@ -1,17 +1,13 @@
use std::{collections::HashMap, sync::Arc}; use std::{collections::HashMap, fmt::Debug, sync::Arc};
use crate::{enums::ProtocolVersion, state::AtemState}; use crate::{enums::ProtocolVersion, state::AtemState};
pub trait DeserializedCommand: Send + Sync { pub trait DeserializedCommand: Send + Sync + Debug {
fn deserialize(buffer: &[u8]) -> Self
where
Self: Sized;
fn apply_to_state(&self, state: &mut AtemState) -> Vec<String>; fn apply_to_state(&self, state: &mut AtemState) -> Vec<String>;
} }
pub trait DeserializableCommand: DeserializedCommand { pub trait CommandDeserializer: Send + Sync {
fn get_raw_name(&self) -> &'static str; fn deserialize(&self, buffer: &[u8]) -> Arc<dyn DeserializedCommand>;
fn get_minimum_version(&self) -> ProtocolVersion;
} }
pub trait SerializableCommand { pub trait SerializableCommand {
@ -19,7 +15,7 @@ pub trait SerializableCommand {
} }
pub trait BasicWritableCommand: SerializableCommand { pub trait BasicWritableCommand: SerializableCommand {
fn get_raw_name(&self) -> &'static str; fn get_raw_name() -> &'static str;
fn get_minimum_version(&self) -> ProtocolVersion; fn get_minimum_version(&self) -> ProtocolVersion;
} }
@ -28,5 +24,3 @@ pub trait WritableCommand: BasicWritableCommand {
fn get_flag(&self) -> f64; fn get_flag(&self) -> f64;
fn set_flag(&mut self, flag: f64); fn set_flag(&mut self, flag: f64);
} }
pub trait SymmetricalCommand: DeserializableCommand + SerializableCommand {}

View File

@ -1,9 +1,13 @@
use crate::commands::command_base::{BasicWritableCommand, SerializableCommand}; use std::sync::Arc;
#[derive(new)] use crate::commands::command_base::{
BasicWritableCommand, CommandDeserializer, DeserializedCommand, SerializableCommand,
};
#[derive(Debug, new)]
pub struct ProgramInput { pub struct ProgramInput {
mix_effect: u8, pub mix_effect: u8,
source: u16, pub source: u16,
} }
impl SerializableCommand for ProgramInput { impl SerializableCommand for ProgramInput {
@ -17,7 +21,7 @@ impl SerializableCommand for ProgramInput {
} }
impl BasicWritableCommand for ProgramInput { impl BasicWritableCommand for ProgramInput {
fn get_raw_name(&self) -> &'static str { fn get_raw_name() -> &'static str {
"CPgI" "CPgI"
} }
@ -25,3 +29,21 @@ impl BasicWritableCommand for ProgramInput {
crate::enums::ProtocolVersion::Unknown crate::enums::ProtocolVersion::Unknown
} }
} }
impl DeserializedCommand for ProgramInput {
fn apply_to_state(&self, state: &mut crate::state::AtemState) -> Vec<String> {
todo!()
}
}
#[derive(Default)]
pub struct ProgramInputDeserializer {}
impl CommandDeserializer for ProgramInputDeserializer {
fn deserialize(&self, buffer: &[u8]) -> Arc<dyn DeserializedCommand> {
let mix_effect = buffer[0];
let source = u16::from_be_bytes([buffer[2], buffer[3]]);
Arc::new(ProgramInput { mix_effect, source })
}
}

View File

@ -1,15 +1,16 @@
use std::sync::Arc; use std::{collections::VecDeque, sync::Arc};
use crate::commands::tally_by_source::TallyBySource; use super::{
command_base::{CommandDeserializer, DeserializedCommand},
mix_effects::program_input::ProgramInputDeserializer,
tally_by_source::TallyBySourceDeserializer,
};
use super::command_base::DeserializedCommand; pub fn deserialize_commands(payload: &[u8]) -> VecDeque<Arc<dyn DeserializedCommand>> {
let mut parsed_commands = VecDeque::new();
pub fn deserialize_commands(payload: &[u8]) -> Vec<Arc<dyn DeserializedCommand>> {
let mut parsed_commands = vec![];
let mut head = 0; let mut head = 0;
while payload.len() > head + 8 { while payload.len() > head + 8 {
// log::debug!("Head at {} out of {}", head, payload.len());
let length = u16::from_be_bytes([payload[head], payload[head + 1]]) as usize; let length = u16::from_be_bytes([payload[head], payload[head + 1]]) as usize;
let Ok(name) = String::from_utf8(payload[(head + 4)..(head + 8)].to_vec()) else { let Ok(name) = String::from_utf8(payload[(head + 4)..(head + 8)].to_vec()) else {
break; break;
@ -21,19 +22,10 @@ pub fn deserialize_commands(payload: &[u8]) -> Vec<Arc<dyn DeserializedCommand>>
log::debug!("Received command {} with length {}", name, length); log::debug!("Received command {} with length {}", name, length);
match name.as_str() { if let Some(deserializer) = command_deserializer_from_string(name.as_str()) {
"TlSr" => { let deserialized_command = deserializer.deserialize(&payload[head + 8..head + length]);
let tally = TallyBySource::deserialize(&payload[head + 8..head + length]); log::debug!("Received {:?}", deserialized_command);
for (source, state) in tally.sources { parsed_commands.push_back(deserialized_command);
log::info!(
"Source {} Program: {}, Preview: {}",
source,
state.program,
state.preview
)
}
}
_ => {}
} }
head += length; head += length;
@ -41,3 +33,11 @@ pub fn deserialize_commands(payload: &[u8]) -> Vec<Arc<dyn DeserializedCommand>>
parsed_commands parsed_commands
} }
fn command_deserializer_from_string(command_str: &str) -> Option<Box<dyn CommandDeserializer>> {
match command_str {
"PrgI" => Some(Box::<ProgramInputDeserializer>::default()),
"TlSr" => Some(Box::<TallyBySourceDeserializer>::default()),
_ => None,
}
}

View File

@ -1,31 +1,29 @@
use std::collections::HashMap; use std::{collections::HashMap, sync::Arc};
use crate::commands::command_base::{BasicWritableCommand, SerializableCommand}; use super::command_base::{CommandDeserializer, DeserializedCommand};
use super::command_base::{DeserializableCommand, DeserializedCommand};
#[derive(Debug)]
pub struct TallySource { pub struct TallySource {
pub program: bool, pub program: bool,
pub preview: bool, pub preview: bool,
} }
#[derive(new)] #[derive(Debug, new)]
pub struct TallyBySource { pub struct TallyBySource {
pub sources: HashMap<u16, TallySource>, pub sources: HashMap<u16, TallySource>,
} }
impl DeserializableCommand for TallyBySource { impl DeserializedCommand for TallyBySource {
fn get_raw_name(&self) -> &'static str { fn apply_to_state(&self, state: &mut crate::state::AtemState) -> Vec<String> {
"TlSr" todo!()
}
fn get_minimum_version(&self) -> crate::enums::ProtocolVersion {
crate::enums::ProtocolVersion::Unknown
} }
} }
impl DeserializedCommand for TallyBySource { #[derive(Default)]
fn deserialize(buffer: &[u8]) -> Self { pub struct TallyBySourceDeserializer {}
impl CommandDeserializer for TallyBySourceDeserializer {
fn deserialize(&self, buffer: &[u8]) -> Arc<dyn DeserializedCommand> {
let source_count = u16::from_be_bytes([buffer[0], buffer[1]]) as usize; let source_count = u16::from_be_bytes([buffer[0], buffer[1]]) as usize;
log::debug!("{:?}", buffer); log::debug!("{:?}", buffer);
@ -47,10 +45,6 @@ impl DeserializedCommand for TallyBySource {
); );
} }
Self { sources } Arc::new(TallyBySource { sources })
}
fn apply_to_state(&self, state: &mut crate::state::AtemState) -> Vec<String> {
todo!()
} }
} }