matc/clusters/codec/
audio_output.rs1use crate::tlv;
7use anyhow;
8use serde_json;
9
10
11#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
14#[repr(u8)]
15pub enum OutputType {
16 Hdmi = 0,
18 Bt = 1,
19 Optical = 2,
20 Headphone = 3,
21 Internal = 4,
22 Other = 5,
23}
24
25impl OutputType {
26 pub fn from_u8(value: u8) -> Option<Self> {
28 match value {
29 0 => Some(OutputType::Hdmi),
30 1 => Some(OutputType::Bt),
31 2 => Some(OutputType::Optical),
32 3 => Some(OutputType::Headphone),
33 4 => Some(OutputType::Internal),
34 5 => Some(OutputType::Other),
35 _ => None,
36 }
37 }
38
39 pub fn to_u8(self) -> u8 {
41 self as u8
42 }
43}
44
45impl From<OutputType> for u8 {
46 fn from(val: OutputType) -> Self {
47 val as u8
48 }
49}
50
51#[derive(Debug, serde::Serialize)]
54pub struct OutputInfo {
55 pub index: Option<u8>,
56 pub output_type: Option<OutputType>,
57 pub name: Option<String>,
58}
59
60pub fn encode_select_output(index: u8) -> anyhow::Result<Vec<u8>> {
64 let tlv = tlv::TlvItemEnc {
65 tag: 0,
66 value: tlv::TlvItemValueEnc::StructInvisible(vec![
67 (0, tlv::TlvItemValueEnc::UInt8(index)).into(),
68 ]),
69 };
70 Ok(tlv.encode()?)
71}
72
73pub fn encode_rename_output(index: u8, name: String) -> anyhow::Result<Vec<u8>> {
75 let tlv = tlv::TlvItemEnc {
76 tag: 0,
77 value: tlv::TlvItemValueEnc::StructInvisible(vec![
78 (0, tlv::TlvItemValueEnc::UInt8(index)).into(),
79 (1, tlv::TlvItemValueEnc::String(name)).into(),
80 ]),
81 };
82 Ok(tlv.encode()?)
83}
84
85pub fn decode_output_list(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<OutputInfo>> {
89 let mut res = Vec::new();
90 if let tlv::TlvItemValue::List(v) = inp {
91 for item in v {
92 res.push(OutputInfo {
93 index: item.get_int(&[0]).map(|v| v as u8),
94 output_type: item.get_int(&[1]).and_then(|v| OutputType::from_u8(v as u8)),
95 name: item.get_string_owned(&[2]),
96 });
97 }
98 }
99 Ok(res)
100}
101
102pub fn decode_current_output(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
104 if let tlv::TlvItemValue::Int(v) = inp {
105 Ok(*v as u8)
106 } else {
107 Err(anyhow::anyhow!("Expected UInt8"))
108 }
109}
110
111
112pub fn decode_attribute_json(cluster_id: u32, attribute_id: u32, tlv_value: &crate::tlv::TlvItemValue) -> String {
124 if cluster_id != 0x050B {
126 return format!("{{\"error\": \"Invalid cluster ID. Expected 0x050B, got {}\"}}", cluster_id);
127 }
128
129 match attribute_id {
130 0x0000 => {
131 match decode_output_list(tlv_value) {
132 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
133 Err(e) => format!("{{\"error\": \"{}\"}}", e),
134 }
135 }
136 0x0001 => {
137 match decode_current_output(tlv_value) {
138 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
139 Err(e) => format!("{{\"error\": \"{}\"}}", e),
140 }
141 }
142 _ => format!("{{\"error\": \"Unknown attribute ID: {}\"}}", attribute_id),
143 }
144}
145
146pub fn get_attribute_list() -> Vec<(u32, &'static str)> {
151 vec![
152 (0x0000, "OutputList"),
153 (0x0001, "CurrentOutput"),
154 ]
155}
156