use super::Remote;
use irp::{Decoder, InfraredData, Irp, Options, DFA, NFA};
use log::debug;
pub struct LircDecoder<'a> {
pub remote: &'a Remote,
pub dfa: DFA,
pub decoder: Decoder<'a>,
}
impl Remote {
pub fn default_options(
&self,
abs_tolerance: Option<u32>,
rel_tolerance: Option<u32>,
max_gap: u32,
) -> Options {
Options {
name: &self.name,
aeps: abs_tolerance.unwrap_or(self.aeps as u32),
eps: rel_tolerance.unwrap_or(self.eps as u32),
max_gap,
..Default::default()
}
}
pub fn build_dfa<'b>(&'b self, options: &Options<'b>) -> DFA {
let nfa = if self.raw_codes.is_empty() {
let irp = self.decode_irp();
debug!("decoding irp {irp} for remote {}", self.name);
let irp = Irp::parse(&irp).unwrap();
irp.build_nfa().unwrap()
} else {
let mut nfa = NFA::default();
for (i, raw) in self.raw_codes.iter().enumerate() {
let message = self.encode_once(raw);
nfa.add_raw(&message.raw, irp::Event::Down, u32::MAX as i64 + i as i64);
}
nfa
};
nfa.build_dfa(options)
}
pub fn decoder<'b>(&'b self, options: Options<'b>) -> LircDecoder<'b> {
let dfa = self.build_dfa(&options);
let decoder = Decoder::new(options);
LircDecoder {
remote: self,
dfa,
decoder,
}
}
}
impl<'a> LircDecoder<'a> {
pub fn input<F>(&mut self, ir: InfraredData, mut callback: F)
where
F: FnMut(&'a str, u64),
{
self.decoder.dfa_input(ir, &self.dfa, |_, vars| {
if let Some(decoded) = vars.get("CODE") {
if self.remote.raw_codes.is_empty() {
let (mask, toggle_bit_mask) = if self.remote.single_toggle_bit() {
(!(self.remote.toggle_bit_mask | self.remote.ignore_mask), 0)
} else {
(!self.remote.ignore_mask, self.remote.toggle_bit_mask)
};
let decoded = *decoded as u64;
if let Some(key_code) = self.remote.codes.iter().find(|code| {
let code = code.code[0] & mask;
let decoded_masked = decoded & mask;
code == decoded_masked
|| code == (decoded_masked ^ self.remote.repeat_mask)
|| (code == (decoded_masked ^ toggle_bit_mask))
}) {
callback(&key_code.name, decoded);
}
} else {
let decoded: usize = *decoded as usize - u32::MAX as usize;
callback(&self.remote.raw_codes[decoded].name, decoded as u64);
}
}
})
}
pub fn reset(&mut self) {
self.decoder.reset();
}
}