blob: c8a8530f348f44f45c3bfae920f9168e977644e0 [file] [log] [blame]
// Copyright 2023 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
pub mod codec_capabilities;
pub mod codec_configuration;
pub mod metadata_ltv;
use crate::{codable_as_bitmask, decodable_enum};
// Source:
// https://bitbucket.org/bluetooth-SIG/public/src/main/assigned_numbers/profiles_and_services/generic_audio/context_type.yaml
decodable_enum! {
pub enum ContextType<u16, crate::packet_encoding::Error, OutOfRange> {
Unspecified = 0x0001,
Conversational = 0x0002,
Media = 0x0004,
Game = 0x0008,
Instructional = 0x0010,
VoiceAssistants = 0x0020,
Live = 0x0040,
SoundEffects = 0x0080,
Notifications = 0x0100,
Ringtone = 0x0200,
Alerts = 0x0400,
EmergencyAlarm = 0x0800,
}
}
codable_as_bitmask!(ContextType, u16);
// Source:
// https://bitbucket.org/bluetooth-SIG/public/src/main/assigned_numbers/profiles_and_services/generic_audio/audio_location_definitions.yaml
// Regexp magic for quick variants:
// %s/ - value: \(\S\+\)\n audio_location: \(.*\)\n/\2 = \1\r,/g
// with subsequent removal of Spaces
decodable_enum! {
pub enum AudioLocation<u32, crate::packet_encoding::Error, OutOfRange> {
FrontLeft = 0x00000001,
FrontRight = 0x00000002,
FrontCenter = 0x00000004,
LowFrequencyEffects1 = 0x00000008,
BackLeft = 0x00000010,
BackRight = 0x00000020,
FrontLeftOfCenter = 0x00000040,
FrontRightOfCenter = 0x00000080,
BackCenter = 0x00000100,
LowFrequencyEffects2 = 0x00000200,
SideLeft = 0x00000400,
SideRight = 0x00000800,
TopFrontLeft = 0x00001000,
TopFrontRight = 0x00002000,
TopFrontCenter = 0x00004000,
TopCenter = 0x00008000,
TopBackLeft = 0x00010000,
TopBackRight = 0x00020000,
TopSideLeft = 0x00040000,
TopSideRight = 0x00080000,
TopBackCenter = 0x00100000,
BottomFrontCenter = 0x00200000,
BottomFrontLeft = 0x00400000,
BottomFrontRight = 0x00800000,
FrontLeftWide = 0x01000000,
FrontRightWide = 0x02000000,
LeftSurround = 0x04000000,
RightSurround = 0x08000000,
}
}
codable_as_bitmask!(AudioLocation, u32);
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn locations_decodable() {
let five_point_one = 0b111111;
let locations: std::collections::HashSet<AudioLocation> =
AudioLocation::from_bits(five_point_one).collect();
assert_eq!(6, locations.len());
let expected_locations = [
AudioLocation::FrontLeft,
AudioLocation::FrontRight,
AudioLocation::FrontCenter,
AudioLocation::LowFrequencyEffects1,
AudioLocation::BackLeft,
AudioLocation::BackRight,
]
.into_iter()
.collect();
assert_eq!(locations, expected_locations);
assert_eq!(AudioLocation::try_from(0x4), Ok(AudioLocation::FrontCenter));
// Directly decoding a location that is not a single bit is an error.
assert!(AudioLocation::try_from(0b1010101).is_err());
}
#[test]
fn locations_encodable() {
let locations_missing_sub = [
AudioLocation::FrontLeft,
AudioLocation::FrontRight,
AudioLocation::FrontCenter,
AudioLocation::BackLeft,
AudioLocation::BackRight,
];
let value = AudioLocation::to_bits(locations_missing_sub.iter());
assert_eq!(0b110111, value);
}
#[test]
fn context_type_decodable() {
let contexts: Vec<ContextType> = ContextType::from_bits(0b10).collect();
assert_eq!(contexts.len(), 1);
assert_eq!(contexts[0], ContextType::Conversational);
let live_and_instructional = 0b1010000;
let contexts: std::collections::HashSet<ContextType> =
ContextType::from_bits(live_and_instructional).collect();
assert_eq!(contexts.len(), 2);
assert_eq!(contexts, [ContextType::Live, ContextType::Instructional].into_iter().collect());
let alerts_and_conversational = 0x0402;
let contexts: std::collections::HashSet<ContextType> =
ContextType::from_bits(alerts_and_conversational).collect();
assert_eq!(contexts.len(), 2);
assert_eq!(
contexts,
[ContextType::Alerts, ContextType::Conversational].into_iter().collect()
);
}
#[test]
fn context_type_encodable() {
let contexts = [ContextType::Notifications, ContextType::SoundEffects, ContextType::Game];
let value = ContextType::to_bits(contexts.iter());
assert_eq!(0x188, value);
}
}