wip: _top
This commit is contained in:
		
							parent
							
								
									493bf7a6e8
								
							
						
					
					
						commit
						d2f41821c0
					
				| @ -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 | ||||
|  | ||||
| @ -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 { | ||||
|  | ||||
| @ -1,2 +1,3 @@ | ||||
| pub mod product_identifier; | ||||
| pub mod topology; | ||||
| pub mod version; | ||||
|  | ||||
| @ -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') | ||||
|  | ||||
							
								
								
									
										91
									
								
								atem-connection-rs/src/commands/device_profile/topology.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								atem-connection-rs/src/commands/device_profile/topology.rs
									
									
									
									
									
										Normal 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, | ||||
|         }) | ||||
|     } | ||||
| } | ||||
| @ -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"); | ||||
| 
 | ||||
|  | ||||
| @ -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 {}) | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -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]]); | ||||
| 
 | ||||
|  | ||||
| @ -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; | ||||
|  | ||||
| @ -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); | ||||
|  | ||||
| @ -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], | ||||
|  | ||||
| @ -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, | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user