use crate::api;
use crate::api::consts::{MAX_LABEL, MAX_SHORT_LABEL};
pub struct ChannelInfo {
name: String,
short_name: String,
active: bool,
arrangement_type: SpeakerArrangementType,
}
impl ChannelInfo {
pub fn new(
name: String,
short_name: Option<String>,
active: bool,
arrangement_type: Option<SpeakerArrangementType>,
) -> ChannelInfo {
ChannelInfo {
name: name.clone(),
short_name: if let Some(short_name) = short_name {
short_name
} else {
name
},
active,
arrangement_type: arrangement_type.unwrap_or(SpeakerArrangementType::Custom),
}
}
}
impl Into<api::ChannelProperties> for ChannelInfo {
fn into(self) -> api::ChannelProperties {
api::ChannelProperties {
name: {
let mut label = [0; MAX_LABEL as usize];
for (b, c) in self.name.bytes().zip(label.iter_mut()) {
*c = b;
}
label
},
flags: {
let mut flag = api::ChannelFlags::empty();
if self.active {
flag |= api::ChannelFlags::ACTIVE
}
if self.arrangement_type.is_left_stereo() {
flag |= api::ChannelFlags::STEREO
}
if self.arrangement_type.is_speaker_type() {
flag |= api::ChannelFlags::SPEAKER
}
flag.bits()
},
arrangement_type: self.arrangement_type.into(),
short_name: {
let mut label = [0; MAX_SHORT_LABEL as usize];
for (b, c) in self.short_name.bytes().zip(label.iter_mut()) {
*c = b;
}
label
},
future: [0; 48],
}
}
}
impl From<api::ChannelProperties> for ChannelInfo {
fn from(api: api::ChannelProperties) -> ChannelInfo {
ChannelInfo {
name: String::from_utf8_lossy(&api.name).to_string(),
short_name: String::from_utf8_lossy(&api.short_name).to_string(),
active: api::ChannelFlags::from_bits(api.flags)
.expect("Invalid bits in channel info")
.intersects(api::ChannelFlags::ACTIVE),
arrangement_type: SpeakerArrangementType::from(api),
}
}
}
pub enum ArrangementTarget {
Music,
Cinema,
}
pub enum StereoChannel {
Left,
Right,
}
#[allow(non_camel_case_types)]
pub enum StereoConfig {
L_R,
Ls_Rs,
Lc_Rc,
Sl_Sr,
C_Lfe,
}
#[allow(non_camel_case_types)]
pub enum SurroundConfig {
S3_0(ArrangementTarget),
S3_1(ArrangementTarget),
S4_0(ArrangementTarget),
S4_1(ArrangementTarget),
S5_0,
S5_1,
S6_0(ArrangementTarget),
S6_1(ArrangementTarget),
S7_0(ArrangementTarget),
S7_1(ArrangementTarget),
S8_0(ArrangementTarget),
S8_1(ArrangementTarget),
S10_2,
}
pub enum SpeakerArrangementType {
Custom,
Empty,
Mono,
Stereo(StereoConfig, StereoChannel),
Surround(SurroundConfig),
}
impl Default for SpeakerArrangementType {
fn default() -> SpeakerArrangementType {
SpeakerArrangementType::Mono
}
}
impl SpeakerArrangementType {
pub fn is_speaker_type(&self) -> bool {
if let SpeakerArrangementType::Surround(..) = *self {
true
} else {
false
}
}
pub fn is_left_stereo(&self) -> bool {
if let SpeakerArrangementType::Stereo(_, StereoChannel::Left) = *self {
true
} else {
false
}
}
}
impl Into<api::SpeakerArrangementType> for SpeakerArrangementType {
fn into(self) -> api::SpeakerArrangementType {
use self::ArrangementTarget::{Cinema, Music};
use self::SpeakerArrangementType::*;
use api::SpeakerArrangementType as Raw;
match self {
Custom => Raw::Custom,
Empty => Raw::Empty,
Mono => Raw::Mono,
Stereo(conf, _) => {
match conf {
StereoConfig::L_R => Raw::Stereo,
StereoConfig::Ls_Rs => Raw::StereoSurround,
StereoConfig::Lc_Rc => Raw::StereoCenter,
StereoConfig::Sl_Sr => Raw::StereoSide,
StereoConfig::C_Lfe => Raw::StereoCLfe,
}
}
Surround(conf) => {
match conf {
SurroundConfig::S3_0(Music) => Raw::Music30,
SurroundConfig::S3_0(Cinema) => Raw::Cinema30,
SurroundConfig::S3_1(Music) => Raw::Music31,
SurroundConfig::S3_1(Cinema) => Raw::Cinema31,
SurroundConfig::S4_0(Music) => Raw::Music40,
SurroundConfig::S4_0(Cinema) => Raw::Cinema40,
SurroundConfig::S4_1(Music) => Raw::Music41,
SurroundConfig::S4_1(Cinema) => Raw::Cinema41,
SurroundConfig::S5_0 => Raw::Surround50,
SurroundConfig::S5_1 => Raw::Surround51,
SurroundConfig::S6_0(Music) => Raw::Music60,
SurroundConfig::S6_0(Cinema) => Raw::Cinema60,
SurroundConfig::S6_1(Music) => Raw::Music61,
SurroundConfig::S6_1(Cinema) => Raw::Cinema61,
SurroundConfig::S7_0(Music) => Raw::Music70,
SurroundConfig::S7_0(Cinema) => Raw::Cinema70,
SurroundConfig::S7_1(Music) => Raw::Music71,
SurroundConfig::S7_1(Cinema) => Raw::Cinema71,
SurroundConfig::S8_0(Music) => Raw::Music80,
SurroundConfig::S8_0(Cinema) => Raw::Cinema80,
SurroundConfig::S8_1(Music) => Raw::Music81,
SurroundConfig::S8_1(Cinema) => Raw::Cinema81,
SurroundConfig::S10_2 => Raw::Surround102,
}
}
}
}
}
impl From<api::ChannelProperties> for SpeakerArrangementType {
fn from(api: api::ChannelProperties) -> SpeakerArrangementType {
use self::ArrangementTarget::{Cinema, Music};
use self::SpeakerArrangementType::*;
use self::SurroundConfig::*;
use api::SpeakerArrangementType as Raw;
let stereo = if api::ChannelFlags::from_bits(api.flags)
.expect("Invalid Channel Flags")
.intersects(api::ChannelFlags::STEREO)
{
StereoChannel::Left
} else {
StereoChannel::Right
};
match api.arrangement_type {
Raw::Custom => Custom,
Raw::Empty => Empty,
Raw::Mono => Mono,
Raw::Stereo => Stereo(StereoConfig::L_R, stereo),
Raw::StereoSurround => Stereo(StereoConfig::Ls_Rs, stereo),
Raw::StereoCenter => Stereo(StereoConfig::Lc_Rc, stereo),
Raw::StereoSide => Stereo(StereoConfig::Sl_Sr, stereo),
Raw::StereoCLfe => Stereo(StereoConfig::C_Lfe, stereo),
Raw::Music30 => Surround(S3_0(Music)),
Raw::Cinema30 => Surround(S3_0(Cinema)),
Raw::Music31 => Surround(S3_1(Music)),
Raw::Cinema31 => Surround(S3_1(Cinema)),
Raw::Music40 => Surround(S4_0(Music)),
Raw::Cinema40 => Surround(S4_0(Cinema)),
Raw::Music41 => Surround(S4_1(Music)),
Raw::Cinema41 => Surround(S4_1(Cinema)),
Raw::Surround50 => Surround(S5_0),
Raw::Surround51 => Surround(S5_1),
Raw::Music60 => Surround(S6_0(Music)),
Raw::Cinema60 => Surround(S6_0(Cinema)),
Raw::Music61 => Surround(S6_1(Music)),
Raw::Cinema61 => Surround(S6_1(Cinema)),
Raw::Music70 => Surround(S7_0(Music)),
Raw::Cinema70 => Surround(S7_0(Cinema)),
Raw::Music71 => Surround(S7_1(Music)),
Raw::Cinema71 => Surround(S7_1(Cinema)),
Raw::Music80 => Surround(S8_0(Music)),
Raw::Cinema80 => Surround(S8_0(Cinema)),
Raw::Music81 => Surround(S8_1(Music)),
Raw::Cinema81 => Surround(S8_1(Cinema)),
Raw::Surround102 => Surround(S10_2),
}
}
}