feat: _pin command

This commit is contained in:
Baud 2024-03-17 14:16:00 +00:00
parent c5ed966070
commit 493bf7a6e8
6 changed files with 166 additions and 37 deletions

View File

@ -11,7 +11,7 @@ use crate::{
atem_lib::atem_socket::{AtemEvent, AtemSocketCommand, AtemSocketMessage, TrackingId},
commands::{
command_base::{BasicWritableCommand, DeserializedCommand},
device_profile::DESERIALIZE_VERSION_RAW_NAME,
device_profile::version::DESERIALIZE_VERSION_RAW_NAME,
init_complete::DESERIALIZE_INIT_COMPLETE_RAW_NAME,
time::DESERIALIZE_TIME_RAW_NAME,
},

View File

@ -1,34 +1,2 @@
use std::sync::Arc;
use crate::enums::ProtocolVersion;
use super::command_base::{CommandDeserializer, DeserializedCommand};
pub const DESERIALIZE_VERSION_RAW_NAME: &str = "_ver";
#[derive(Debug)]
pub struct VersionCommand {
pub version: ProtocolVersion,
}
impl DeserializedCommand for VersionCommand {
fn raw_name(&self) -> &'static str {
DESERIALIZE_VERSION_RAW_NAME
}
fn apply_to_state(&self, state: &mut crate::state::AtemState) {
state.info.api_version = self.version;
}
}
#[derive(Default)]
pub struct VersionCommandDeserializer {}
impl CommandDeserializer for VersionCommandDeserializer {
fn deserialize(&self, buffer: &[u8]) -> 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");
Arc::new(VersionCommand { version })
}
}
pub mod product_identifier;
pub mod version;

View File

@ -0,0 +1,64 @@
use std::{ffi::CString, sync::Arc};
use crate::{
commands::command_base::{CommandDeserializer, DeserializedCommand},
enums::Model,
};
pub const DESERIALIZE_PRODUCT_IDENTIFIER_RAW_NAME: &str = "_pin";
#[derive(Debug)]
pub struct ProductIdentifierCommand {
pub product_identifier: String,
pub model: Model,
}
impl DeserializedCommand for ProductIdentifierCommand {
fn raw_name(&self) -> &'static str {
DESERIALIZE_PRODUCT_IDENTIFIER_RAW_NAME
}
fn apply_to_state(&self, state: &mut crate::state::AtemState) {
state.info.product_identifier = Some(self.product_identifier.clone());
state.info.model = self.model.clone();
match state.info.model {
Model::TwoME
| Model::TwoME4K
| Model::TwoMEBS4K
| Model::Constellation
| Model::Constellation8K
| Model::ConstellationHD4ME
| Model::Constellation4K4ME => {
state.info.power = vec![false, false];
}
_ => {
state.info.power = vec![false];
}
}
}
}
#[derive(Default)]
pub struct ProductIdentifierCommandDeserializer {}
impl CommandDeserializer for ProductIdentifierCommandDeserializer {
fn deserialize(&self, buffer: &[u8]) -> std::sync::Arc<dyn DeserializedCommand> {
let null_byte_index = buffer
.iter()
.position(|byte| *byte == b'\0')
.expect("No null byte");
let product_identifier =
CString::from_vec_with_nul(buffer[..(null_byte_index + 1)].to_vec())
.expect("Malformed string");
let model = buffer[40];
Arc::new(ProductIdentifierCommand {
product_identifier: product_identifier
.to_str()
.expect("Invalid rust string")
.to_string(),
model: model.into(),
})
}
}

View File

@ -0,0 +1,35 @@
use std::sync::Arc;
use crate::{
commands::command_base::{CommandDeserializer, DeserializedCommand},
enums::ProtocolVersion,
};
pub const DESERIALIZE_VERSION_RAW_NAME: &str = "_ver";
#[derive(Debug)]
pub struct VersionCommand {
pub version: ProtocolVersion,
}
impl DeserializedCommand for VersionCommand {
fn raw_name(&self) -> &'static str {
DESERIALIZE_VERSION_RAW_NAME
}
fn apply_to_state(&self, state: &mut crate::state::AtemState) {
state.info.api_version = self.version;
}
}
#[derive(Default)]
pub struct VersionCommandDeserializer {}
impl CommandDeserializer for VersionCommandDeserializer {
fn deserialize(&self, buffer: &[u8]) -> 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");
Arc::new(VersionCommand { version })
}
}

View File

@ -2,7 +2,12 @@ use std::{collections::VecDeque, sync::Arc};
use super::{
command_base::{CommandDeserializer, DeserializedCommand},
device_profile::{VersionCommandDeserializer, DESERIALIZE_VERSION_RAW_NAME},
device_profile::{
product_identifier::{
ProductIdentifierCommandDeserializer, DESERIALIZE_PRODUCT_IDENTIFIER_RAW_NAME,
},
version::{VersionCommandDeserializer, DESERIALIZE_VERSION_RAW_NAME},
},
init_complete::{InitCompleteDeserializer, DESERIALIZE_INIT_COMPLETE_RAW_NAME},
mix_effects::program_input::{ProgramInputDeserializer, DESERIALIZE_PROGRAM_INPUT_RAW_NAME},
tally_by_source::{TallyBySourceDeserializer, DESERIALIZE_TALLY_BY_SOURCE_RAW_NAME},
@ -29,6 +34,10 @@ pub fn deserialize_commands(payload: &[u8]) -> VecDeque<Arc<dyn DeserializedComm
let deserialized_command = deserializer.deserialize(&payload[head + 8..head + length]);
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}.");
}
head += length;
@ -44,6 +53,9 @@ fn command_deserializer_from_string(command_str: &str) -> Option<Box<dyn Command
DESERIALIZE_PROGRAM_INPUT_RAW_NAME => Some(Box::<ProgramInputDeserializer>::default()),
DESERIALIZE_TALLY_BY_SOURCE_RAW_NAME => Some(Box::<TallyBySourceDeserializer>::default()),
DESERIALIZE_TIME_RAW_NAME => Some(Box::<TimeDeserializer>::default()),
DESERIALIZE_PRODUCT_IDENTIFIER_RAW_NAME => {
Some(Box::<ProductIdentifierCommandDeserializer>::default())
}
_ => None,
}
}

View File

@ -1,4 +1,4 @@
#[derive(Clone, Default, PartialEq)]
#[derive(Debug, Clone, Default, PartialEq)]
pub enum Model {
#[default]
Unknown = 0x00,
@ -19,6 +19,56 @@ pub enum Model {
MiniProISO = 0x0f,
MiniExtreme = 0x10,
MiniExtremeISO = 0x11,
ConstellationHD1ME = 0x12,
ConstellationHD2ME = 0x13,
ConstellationHD4ME = 0x14,
SDI = 0x15,
SDIProISO = 0x16,
SDIExtremeISO = 0x17,
// 0x18 ??
// 0x19 ??
TelevisionStudioHD8 = 0x1a,
TelevisionStudioHD8ISO = 0x1b,
// 0x1c ??
// 0x1d ??
Constellation4K4ME = 0x1e,
// 0x1f ??
TelevisionStudio4K8 = 0x20,
}
impl From<u8> for Model {
fn from(value: u8) -> Self {
match value {
0x01 => Model::TVS,
0x02 => Model::OneME,
0x03 => Model::TwoME,
0x04 => Model::PS4K,
0x05 => Model::OneME4K,
0x06 => Model::TwoME4K,
0x07 => Model::TwoMEBS4K,
0x08 => Model::TVSHD,
0x09 => Model::TVSProHD,
0x0a => Model::TVSPro4K,
0x0b => Model::Constellation,
0x0c => Model::Constellation8K,
0x0d => Model::Mini,
0x0e => Model::MiniPro,
0x0f => Model::MiniProISO,
0x10 => Model::MiniExtreme,
0x11 => Model::MiniExtremeISO,
0x12 => Model::ConstellationHD1ME,
0x13 => Model::ConstellationHD2ME,
0x14 => Model::ConstellationHD4ME,
0x15 => Model::SDI,
0x16 => Model::SDIProISO,
0x17 => Model::SDIExtremeISO,
0x1a => Model::TelevisionStudioHD8,
0x1b => Model::TelevisionStudioHD8ISO,
0x1e => Model::Constellation4K4ME,
0x20 => Model::TelevisionStudio4K8,
_ => Model::Unknown,
}
}
}
#[derive(Debug, Default, Clone, Copy, PartialEq)]