diff --git a/atem-connection-rs/src/atem_lib/atem_socket_inner.rs b/atem-connection-rs/src/atem_lib/atem_socket_inner.rs index 2584f70..701db76 100644 --- a/atem-connection-rs/src/atem_lib/atem_socket_inner.rs +++ b/atem-connection-rs/src/atem_lib/atem_socket_inner.rs @@ -346,7 +346,7 @@ impl AtemSocketInner { self.send_or_queue_ack().await; if length > 12 { - self.on_command_received(&packet[12..]); + self.on_commands_received(&packet[12..]); } } else if self .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); } diff --git a/atem-connection-rs/src/commands/command_base.rs b/atem-connection-rs/src/commands/command_base.rs index b9ef1c7..b44bf84 100644 --- a/atem-connection-rs/src/commands/command_base.rs +++ b/atem-connection-rs/src/commands/command_base.rs @@ -1,17 +1,13 @@ -use std::{collections::HashMap, sync::Arc}; +use std::{collections::HashMap, fmt::Debug, sync::Arc}; use crate::{enums::ProtocolVersion, state::AtemState}; -pub trait DeserializedCommand: Send + Sync { - fn deserialize(buffer: &[u8]) -> Self - where - Self: Sized; +pub trait DeserializedCommand: Send + Sync + Debug { fn apply_to_state(&self, state: &mut AtemState) -> Vec; } -pub trait DeserializableCommand: DeserializedCommand { - fn get_raw_name(&self) -> &'static str; - fn get_minimum_version(&self) -> ProtocolVersion; +pub trait CommandDeserializer: Send + Sync { + fn deserialize(&self, buffer: &[u8]) -> Arc; } pub trait SerializableCommand { @@ -19,7 +15,7 @@ pub trait SerializableCommand { } pub trait BasicWritableCommand: SerializableCommand { - fn get_raw_name(&self) -> &'static str; + fn get_raw_name() -> &'static str; fn get_minimum_version(&self) -> ProtocolVersion; } @@ -28,5 +24,3 @@ pub trait WritableCommand: BasicWritableCommand { fn get_flag(&self) -> f64; fn set_flag(&mut self, flag: f64); } - -pub trait SymmetricalCommand: DeserializableCommand + SerializableCommand {} diff --git a/atem-connection-rs/src/commands/mix_effects/program_input.rs b/atem-connection-rs/src/commands/mix_effects/program_input.rs index 5248152..618c6bc 100644 --- a/atem-connection-rs/src/commands/mix_effects/program_input.rs +++ b/atem-connection-rs/src/commands/mix_effects/program_input.rs @@ -1,8 +1,10 @@ +use std::sync::Arc; + use crate::commands::command_base::{ - BasicWritableCommand, DeserializableCommand, DeserializedCommand, SerializableCommand, + BasicWritableCommand, CommandDeserializer, DeserializedCommand, SerializableCommand, }; -#[derive(new)] +#[derive(Debug, new)] pub struct ProgramInput { pub mix_effect: u8, pub source: u16, @@ -19,7 +21,7 @@ impl SerializableCommand for ProgramInput { } impl BasicWritableCommand for ProgramInput { - fn get_raw_name(&self) -> &'static str { + fn get_raw_name() -> &'static str { "CPgI" } @@ -28,28 +30,20 @@ impl BasicWritableCommand for ProgramInput { } } -impl DeserializableCommand for ProgramInput { - fn get_raw_name(&self) -> &'static str { - "PrgI" - } - - fn get_minimum_version(&self) -> crate::enums::ProtocolVersion { - crate::enums::ProtocolVersion::Unknown - } -} - impl DeserializedCommand for ProgramInput { - fn deserialize(buffer: &[u8]) -> Self - where - Self: Sized, - { - let mix_effect = buffer[0]; - let source = u16::from_be_bytes([buffer[2], buffer[3]]); - - Self { mix_effect, source } - } - fn apply_to_state(&self, state: &mut crate::state::AtemState) -> Vec { todo!() } } + +#[derive(Default)] +pub struct ProgramInputDeserializer {} + +impl CommandDeserializer for ProgramInputDeserializer { + fn deserialize(&self, buffer: &[u8]) -> Arc { + let mix_effect = buffer[0]; + let source = u16::from_be_bytes([buffer[2], buffer[3]]); + + Arc::new(ProgramInput { mix_effect, source }) + } +} diff --git a/atem-connection-rs/src/commands/parse_commands.rs b/atem-connection-rs/src/commands/parse_commands.rs index 3c2c25a..2ad4aec 100644 --- a/atem-connection-rs/src/commands/parse_commands.rs +++ b/atem-connection-rs/src/commands/parse_commands.rs @@ -1,15 +1,16 @@ -use std::sync::Arc; +use std::{collections::VecDeque, sync::Arc}; -use crate::commands::{mix_effects::program_input::ProgramInput, 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]) -> Vec> { - let mut parsed_commands = vec![]; +pub fn deserialize_commands(payload: &[u8]) -> VecDeque> { + let mut parsed_commands = VecDeque::new(); let mut head = 0; 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 Ok(name) = String::from_utf8(payload[(head + 4)..(head + 8)].to_vec()) else { break; @@ -21,28 +22,10 @@ pub fn deserialize_commands(payload: &[u8]) -> Vec> log::debug!("Received command {} with length {}", name, length); - match name.as_str() { - "TlSr" => { - let tally = TallyBySource::deserialize(&payload[head + 8..head + length]); - for (source, state) in tally.sources { - log::info!( - "Source {} Program: {}, Preview: {}", - source, - state.program, - state.preview - ) - } - } - "PrgI" => { - let program_input = ProgramInput::deserialize(&payload[head + 8..head + length]); - - log::info!( - "Mix Effect {} changed to source {}", - program_input.mix_effect, - program_input.source - ); - } - _ => {} + if let Some(deserializer) = command_deserializer_from_string(name.as_str()) { + let deserialized_command = deserializer.deserialize(&payload[head + 8..head + length]); + log::debug!("Received {:?}", deserialized_command); + parsed_commands.push_back(deserialized_command); } head += length; @@ -50,3 +33,11 @@ pub fn deserialize_commands(payload: &[u8]) -> Vec> parsed_commands } + +fn command_deserializer_from_string(command_str: &str) -> Option> { + match command_str { + "PrgI" => Some(Box::::default()), + "TlSr" => Some(Box::::default()), + _ => None, + } +} diff --git a/atem-connection-rs/src/commands/tally_by_source.rs b/atem-connection-rs/src/commands/tally_by_source.rs index 6019f5c..8d3eeb8 100644 --- a/atem-connection-rs/src/commands/tally_by_source.rs +++ b/atem-connection-rs/src/commands/tally_by_source.rs @@ -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::{DeserializableCommand, DeserializedCommand}; +use super::command_base::{CommandDeserializer, DeserializedCommand}; +#[derive(Debug)] pub struct TallySource { pub program: bool, pub preview: bool, } -#[derive(new)] +#[derive(Debug, new)] pub struct TallyBySource { pub sources: HashMap, } -impl DeserializableCommand for TallyBySource { - fn get_raw_name(&self) -> &'static str { - "TlSr" - } - - fn get_minimum_version(&self) -> crate::enums::ProtocolVersion { - crate::enums::ProtocolVersion::Unknown +impl DeserializedCommand for TallyBySource { + fn apply_to_state(&self, state: &mut crate::state::AtemState) -> Vec { + todo!() } } -impl DeserializedCommand for TallyBySource { - fn deserialize(buffer: &[u8]) -> Self { +#[derive(Default)] +pub struct TallyBySourceDeserializer {} + +impl CommandDeserializer for TallyBySourceDeserializer { + fn deserialize(&self, buffer: &[u8]) -> Arc { let source_count = u16::from_be_bytes([buffer[0], buffer[1]]) as usize; log::debug!("{:?}", buffer); @@ -47,10 +45,6 @@ impl DeserializedCommand for TallyBySource { ); } - Self { sources } - } - - fn apply_to_state(&self, state: &mut crate::state::AtemState) -> Vec { - todo!() + Arc::new(TallyBySource { sources }) } }