bt_common/
generic_audio.rs1pub mod codec_capabilities;
6pub mod codec_configuration;
7pub mod metadata_ltv;
8
9use crate::{codable_as_bitmask, decodable_enum};
10
11decodable_enum! {
14 pub enum ContextType<u16, crate::packet_encoding::Error, OutOfRange> {
15 Unspecified = 0x0001,
16 Conversational = 0x0002,
17 Media = 0x0004,
18 Game = 0x0008,
19 Instructional = 0x0010,
20 VoiceAssistants = 0x0020,
21 Live = 0x0040,
22 SoundEffects = 0x0080,
23 Notifications = 0x0100,
24 Ringtone = 0x0200,
25 Alerts = 0x0400,
26 EmergencyAlarm = 0x0800,
27 }
28}
29
30codable_as_bitmask!(ContextType, u16);
31
32decodable_enum! {
38 pub enum AudioLocation<u32, crate::packet_encoding::Error, OutOfRange> {
39 FrontLeft = 0x00000001,
40 FrontRight = 0x00000002,
41 FrontCenter = 0x00000004,
42 LowFrequencyEffects1 = 0x00000008,
43 BackLeft = 0x00000010,
44 BackRight = 0x00000020,
45 FrontLeftOfCenter = 0x00000040,
46 FrontRightOfCenter = 0x00000080,
47 BackCenter = 0x00000100,
48 LowFrequencyEffects2 = 0x00000200,
49 SideLeft = 0x00000400,
50 SideRight = 0x00000800,
51 TopFrontLeft = 0x00001000,
52 TopFrontRight = 0x00002000,
53 TopFrontCenter = 0x00004000,
54 TopCenter = 0x00008000,
55 TopBackLeft = 0x00010000,
56 TopBackRight = 0x00020000,
57 TopSideLeft = 0x00040000,
58 TopSideRight = 0x00080000,
59 TopBackCenter = 0x00100000,
60 BottomFrontCenter = 0x00200000,
61 BottomFrontLeft = 0x00400000,
62 BottomFrontRight = 0x00800000,
63 FrontLeftWide = 0x01000000,
64 FrontRightWide = 0x02000000,
65 LeftSurround = 0x04000000,
66 RightSurround = 0x08000000,
67 }
68}
69
70codable_as_bitmask!(AudioLocation, u32);
71
72#[cfg(test)]
73mod tests {
74 use super::*;
75
76 #[test]
77 fn locations_decodable() {
78 let five_point_one = 0b111111;
79
80 let locations: std::collections::HashSet<AudioLocation> =
81 AudioLocation::from_bits(five_point_one).collect();
82
83 assert_eq!(6, locations.len());
84
85 let expected_locations = [
86 AudioLocation::FrontLeft,
87 AudioLocation::FrontRight,
88 AudioLocation::FrontCenter,
89 AudioLocation::LowFrequencyEffects1,
90 AudioLocation::BackLeft,
91 AudioLocation::BackRight,
92 ]
93 .into_iter()
94 .collect();
95
96 assert_eq!(locations, expected_locations);
97
98 assert_eq!(AudioLocation::try_from(0x4), Ok(AudioLocation::FrontCenter));
99
100 assert!(AudioLocation::try_from(0b1010101).is_err());
102 }
103
104 #[test]
105 fn locations_encodable() {
106 let locations_missing_sub = [
107 AudioLocation::FrontLeft,
108 AudioLocation::FrontRight,
109 AudioLocation::FrontCenter,
110 AudioLocation::BackLeft,
111 AudioLocation::BackRight,
112 ];
113
114 let value = AudioLocation::to_bits(locations_missing_sub.iter());
115
116 assert_eq!(0b110111, value);
117 }
118
119 #[test]
120 fn context_type_decodable() {
121 let contexts: Vec<ContextType> = ContextType::from_bits(0b10).collect();
122 assert_eq!(contexts.len(), 1);
123 assert_eq!(contexts[0], ContextType::Conversational);
124
125 let live_and_instructional = 0b1010000;
126 let contexts: std::collections::HashSet<ContextType> =
127 ContextType::from_bits(live_and_instructional).collect();
128
129 assert_eq!(contexts.len(), 2);
130 assert_eq!(contexts, [ContextType::Live, ContextType::Instructional].into_iter().collect());
131
132 let alerts_and_conversational = 0x0402;
133
134 let contexts: std::collections::HashSet<ContextType> =
135 ContextType::from_bits(alerts_and_conversational).collect();
136
137 assert_eq!(contexts.len(), 2);
138 assert_eq!(
139 contexts,
140 [ContextType::Alerts, ContextType::Conversational].into_iter().collect()
141 );
142 }
143
144 #[test]
145 fn context_type_encodable() {
146 let contexts = [ContextType::Notifications, ContextType::SoundEffects, ContextType::Game];
147
148 let value = ContextType::to_bits(contexts.iter());
149
150 assert_eq!(0x188, value);
151 }
152}