wip: _top
This commit is contained in:
parent
493bf7a6e8
commit
d2f41821c0
|
@ -103,6 +103,8 @@ pub struct AtemSocket {
|
||||||
socket: Option<UdpSocket>,
|
socket: Option<UdpSocket>,
|
||||||
address: SocketAddr,
|
address: SocketAddr,
|
||||||
|
|
||||||
|
protocol_version: ProtocolVersion,
|
||||||
|
|
||||||
last_received_at: SystemTime,
|
last_received_at: SystemTime,
|
||||||
last_received_packed_id: u16,
|
last_received_packed_id: u16,
|
||||||
in_flight: Vec<InFlightPacket>,
|
in_flight: Vec<InFlightPacket>,
|
||||||
|
@ -159,6 +161,8 @@ impl AtemSocket {
|
||||||
socket: None,
|
socket: None,
|
||||||
address: "0.0.0.0:0".parse().unwrap(),
|
address: "0.0.0.0:0".parse().unwrap(),
|
||||||
|
|
||||||
|
protocol_version: ProtocolVersion::V7_2,
|
||||||
|
|
||||||
last_received_at: SystemTime::now(),
|
last_received_at: SystemTime::now(),
|
||||||
last_received_packed_id: 0,
|
last_received_packed_id: 0,
|
||||||
in_flight: vec![],
|
in_flight: vec![],
|
||||||
|
@ -532,7 +536,7 @@ impl AtemSocket {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_commands_received(&mut self, payload: &[u8]) {
|
fn on_commands_received(&mut self, payload: &[u8]) {
|
||||||
let commands = deserialize_commands(payload);
|
let commands = deserialize_commands(payload, &self.protocol_version);
|
||||||
|
|
||||||
let _ = self
|
let _ = self
|
||||||
.atem_event_tx
|
.atem_event_tx
|
||||||
|
|
|
@ -8,7 +8,8 @@ pub trait DeserializedCommand: Send + Sync + Debug {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait CommandDeserializer: Send + Sync {
|
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 {
|
pub trait SerializableCommand: Send + Sync {
|
||||||
|
|
|
@ -1,2 +1,3 @@
|
||||||
pub mod product_identifier;
|
pub mod product_identifier;
|
||||||
|
pub mod topology;
|
||||||
pub mod version;
|
pub mod version;
|
||||||
|
|
|
@ -2,7 +2,7 @@ use std::{ffi::CString, sync::Arc};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
commands::command_base::{CommandDeserializer, DeserializedCommand},
|
commands::command_base::{CommandDeserializer, DeserializedCommand},
|
||||||
enums::Model,
|
enums::{Model, ProtocolVersion},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const DESERIALIZE_PRODUCT_IDENTIFIER_RAW_NAME: &str = "_pin";
|
pub const DESERIALIZE_PRODUCT_IDENTIFIER_RAW_NAME: &str = "_pin";
|
||||||
|
@ -43,7 +43,11 @@ impl DeserializedCommand for ProductIdentifierCommand {
|
||||||
pub struct ProductIdentifierCommandDeserializer {}
|
pub struct ProductIdentifierCommandDeserializer {}
|
||||||
|
|
||||||
impl CommandDeserializer for 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
|
let null_byte_index = buffer
|
||||||
.iter()
|
.iter()
|
||||||
.position(|byte| *byte == b'\0')
|
.position(|byte| *byte == b'\0')
|
||||||
|
|
|
@ -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 {}
|
pub struct VersionCommandDeserializer {}
|
||||||
|
|
||||||
impl CommandDeserializer for 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 = u32::from_be_bytes([buffer[0], buffer[1], buffer[2], buffer[3]]);
|
||||||
let version: ProtocolVersion = version.try_into().expect("Invalid protocol version");
|
let version: ProtocolVersion = version.try_into().expect("Invalid protocol version");
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use crate::enums::ProtocolVersion;
|
||||||
|
|
||||||
use super::command_base::{CommandDeserializer, DeserializedCommand};
|
use super::command_base::{CommandDeserializer, DeserializedCommand};
|
||||||
|
|
||||||
pub const DESERIALIZE_INIT_COMPLETE_RAW_NAME: &str = "InCm";
|
pub const DESERIALIZE_INIT_COMPLETE_RAW_NAME: &str = "InCm";
|
||||||
|
@ -19,7 +21,11 @@ impl DeserializedCommand for InitComplete {
|
||||||
pub struct InitCompleteDeserializer {}
|
pub struct InitCompleteDeserializer {}
|
||||||
|
|
||||||
impl CommandDeserializer for 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 {})
|
Arc::new(InitComplete {})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ use crate::{
|
||||||
commands::command_base::{
|
commands::command_base::{
|
||||||
BasicWritableCommand, CommandDeserializer, DeserializedCommand, SerializableCommand,
|
BasicWritableCommand, CommandDeserializer, DeserializedCommand, SerializableCommand,
|
||||||
},
|
},
|
||||||
|
enums::ProtocolVersion,
|
||||||
state::util::get_mix_effect,
|
state::util::get_mix_effect,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -58,7 +59,11 @@ impl DeserializedCommand for ProgramInput {
|
||||||
pub struct ProgramInputDeserializer {}
|
pub struct ProgramInputDeserializer {}
|
||||||
|
|
||||||
impl CommandDeserializer for 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 mix_effect = buffer[0];
|
||||||
let source = u16::from_be_bytes([buffer[2], buffer[3]]);
|
let source = u16::from_be_bytes([buffer[2], buffer[3]]);
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
use std::{collections::VecDeque, sync::Arc};
|
use std::{collections::VecDeque, sync::Arc};
|
||||||
|
|
||||||
|
use crate::enums::ProtocolVersion;
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
command_base::{CommandDeserializer, DeserializedCommand},
|
command_base::{CommandDeserializer, DeserializedCommand},
|
||||||
device_profile::{
|
device_profile::{
|
||||||
|
@ -14,7 +16,10 @@ use super::{
|
||||||
time::{TimeDeserializer, DESERIALIZE_TIME_RAW_NAME},
|
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 parsed_commands = VecDeque::new();
|
||||||
let mut head = 0;
|
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);
|
log::debug!("Received command {} with length {}", name, length);
|
||||||
|
|
||||||
if let Some(deserializer) = command_deserializer_from_string(name.as_str()) {
|
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);
|
log::debug!("Received {:?}", deserialized_command);
|
||||||
parsed_commands.push_back(deserialized_command);
|
parsed_commands.push_back(deserialized_command);
|
||||||
} else {
|
} else {
|
||||||
log::warn!("Received command {name} for which there is no deserializer.");
|
log::warn!("Received command {name} for which there is no deserializer.");
|
||||||
// TODO: Remove!
|
// TODO: Remove!
|
||||||
todo!("Write deserializer for {name}.");
|
// todo!("Write deserializer for {name}.");
|
||||||
}
|
}
|
||||||
|
|
||||||
head += length;
|
head += length;
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
use std::{collections::HashMap, sync::Arc};
|
use std::{collections::HashMap, sync::Arc};
|
||||||
|
|
||||||
|
use crate::enums::ProtocolVersion;
|
||||||
|
|
||||||
use super::command_base::{CommandDeserializer, DeserializedCommand};
|
use super::command_base::{CommandDeserializer, DeserializedCommand};
|
||||||
|
|
||||||
pub const DESERIALIZE_TALLY_BY_SOURCE_RAW_NAME: &str = "TlSr";
|
pub const DESERIALIZE_TALLY_BY_SOURCE_RAW_NAME: &str = "TlSr";
|
||||||
|
@ -29,7 +31,11 @@ impl DeserializedCommand for TallyBySource {
|
||||||
pub struct TallyBySourceDeserializer {}
|
pub struct TallyBySourceDeserializer {}
|
||||||
|
|
||||||
impl CommandDeserializer for 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;
|
let source_count = u16::from_be_bytes([buffer[0], buffer[1]]) as usize;
|
||||||
|
|
||||||
log::debug!("{:?}", buffer);
|
log::debug!("{:?}", buffer);
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use crate::enums::ProtocolVersion;
|
||||||
|
|
||||||
use super::command_base::{CommandDeserializer, DeserializedCommand};
|
use super::command_base::{CommandDeserializer, DeserializedCommand};
|
||||||
|
|
||||||
pub const DESERIALIZE_TIME_RAW_NAME: &str = "Time";
|
pub const DESERIALIZE_TIME_RAW_NAME: &str = "Time";
|
||||||
|
@ -33,6 +35,7 @@ impl CommandDeserializer for TimeDeserializer {
|
||||||
fn deserialize(
|
fn deserialize(
|
||||||
&self,
|
&self,
|
||||||
buffer: &[u8],
|
buffer: &[u8],
|
||||||
|
version: &ProtocolVersion,
|
||||||
) -> std::sync::Arc<dyn super::command_base::DeserializedCommand> {
|
) -> std::sync::Arc<dyn super::command_base::DeserializedCommand> {
|
||||||
let info = TimeInfo {
|
let info = TimeInfo {
|
||||||
hour: buffer[0],
|
hour: buffer[0],
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
use std::fmt::Display;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default, PartialEq)]
|
#[derive(Debug, Clone, Default, PartialEq)]
|
||||||
pub enum Model {
|
pub enum Model {
|
||||||
#[default]
|
#[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 {
|
pub enum ProtocolVersion {
|
||||||
#[default]
|
#[default]
|
||||||
Unknown = 0,
|
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)]
|
#[derive(Clone, PartialEq)]
|
||||||
pub enum TransitionStyle {
|
pub enum TransitionStyle {
|
||||||
MIX = 0x00,
|
MIX = 0x00,
|
||||||
|
|
Loading…
Reference in New Issue