From 2a84c142c2bc1a476cd088ed3464af3784472d23 Mon Sep 17 00:00:00 2001 From: Sean Young Date: Mon, 20 May 2024 21:37:57 +0100 Subject: [PATCH] Cleanup transmit cli a bit Signed-off-by: Sean Young --- README.md | 2 +- TODO | 2 +- cir/src/bin/cir.rs | 45 ++++++++++++++++++++++---------- cir/src/bin/commands/transmit.rs | 40 ++++++++-------------------- cir/tests/encode_tests.rs | 3 +++ 5 files changed, 47 insertions(+), 45 deletions(-) diff --git a/README.md b/README.md index e5ebcf3..0062eed 100644 --- a/README.md +++ b/README.md @@ -79,7 +79,7 @@ cir transmit --keymap RM-Y173.lircd.conf --keycode KEY_CHANNELUP ``` Alternatively, you can send raw IR directly like so: ```bash -cir transmit '+9000 -4500 +560' +cir transmit --raw '+9000 -4500 +560' ``` You can also send files or linux kernel scancodes, using the same options like `ir-ctl`. This supports mode2 files or raw IR files. diff --git a/TODO b/TODO index b994019..2b182c0 100644 --- a/TODO +++ b/TODO @@ -12,7 +12,7 @@ Necessary: Nice to have: - ir encode/send needs to read xml file - cir decode irp should read IrpProtocols.xml -- cir transmit rawir -S sony15:12 -r 2 ?? +- cir transmit -S sony15:12 -R 2 ?? - pcmak leading gap not decoded - encoding toggle_bit_mask not used when popcount > 1 - compare against kernel encoder/decoder diff --git a/cir/src/bin/cir.rs b/cir/src/bin/cir.rs index cf33985..6b8267a 100644 --- a/cir/src/bin/cir.rs +++ b/cir/src/bin/cir.rs @@ -187,6 +187,21 @@ fn parse_scankey(arg: &str) -> Result<(u64, String), String> { } } +fn parse_scancode(arg: &str) -> Result<(String, u64), String> { + if let Some((protocol, scancode)) = arg.split_once(':') { + let scancode = if let Some(hex) = scancode.strip_prefix("0x") { + u64::from_str_radix(hex, 16) + } else { + str::parse(scancode) + } + .map_err(|e| format!("{e}"))?; + + Ok((protocol.to_owned(), scancode)) + } else { + Err("missing `:` separator".into()) + } +} + #[cfg(target_os = "linux")] #[derive(Args)] struct Keymap { @@ -297,7 +312,7 @@ struct Transmit { #[arg(long = "dry-run", short = 'n')] dry_run: bool, - /// List the codes in the keymap + /// List the codes in keymap #[arg(long = "list-codes", short = 'l', requires = "KEYMAP")] list_codes: bool, @@ -305,16 +320,17 @@ struct Transmit { #[arg(long = "file", short = 'f', name = "FILE", help_heading = "INPUT")] files: Vec, - /// Send scancode using linux kernel protocols + /// Send scancode using linux kernel protocol #[arg( long = "scancode", short = 'S', name = "SCANCODE", + value_parser = parse_scancode, help_heading = "INPUT" )] - scancodes: Vec, + scancodes: Vec<(String, u64)>, - /// Set gap after each file + /// Trailing gap length if none present #[arg(long = "gap", short = 'g', name = "GAP", help_heading = "INPUT")] gaps: Vec, @@ -322,30 +338,31 @@ struct Transmit { #[arg(long = "pronto", short = 'p', name = "PRONTO", help_heading = "INPUT")] pronto: Vec, - /// Raw IR text - #[arg(name = "RAWIR", help_heading = "INPUT")] + /// Transmit raw IR + #[arg(long = "raw", short = 'r', name = "RAWIR", help_heading = "INPUT")] rawir: Vec, - /// Number of IRP repeats to encode + /// Number of repeats to encode #[arg( long = "repeats", - short = 'r', + short = 'R', value_parser = value_parser!(u64).range(0..99), default_value_t = 0, help_heading = "INPUT" )] repeats: u64, - /// Set input variable like KEY=VALUE + /// Set IRP parameter like KEY=VALUE #[arg( long = "argument", short = 'a', value_delimiter = ',', - help_heading = "INPUT" + help_heading = "INPUT", + name = "ARGUMENT" )] arguments: Vec, - /// IRP Notation + /// Transmit using IRP Notation #[arg(long = "irp", short = 'i', name = "IRP", help_heading = "INPUT")] irp: Vec, @@ -357,7 +374,7 @@ struct Transmit { #[arg(name = "REMOTE", long = "remote", short = 'm', help_heading = "INPUT")] remote: Option, - /// Code from keymap to send + /// Code from keymap to transmit #[arg(name = "CODE", long = "keycode", short = 'K', help_heading = "INPUT")] codes: Vec, @@ -399,7 +416,7 @@ impl Transmit { arg!("CODE", String, Code); arg!("IRP", String, Irp); arg!("GAP", u32, Gap); - arg!("SCANCODE", String, Scancode); + arg!("SCANCODE", (String, u64), Scancode); part.sort_by(|a, b| a.1.cmp(&b.1)); @@ -414,7 +431,7 @@ enum Transmitables { Code(String), Irp(String), Gap(u32), - Scancode(String), + Scancode((String, u64)), } impl FromArgMatches for Commands { diff --git a/cir/src/bin/commands/transmit.rs b/cir/src/bin/commands/transmit.rs index df72a28..131818c 100644 --- a/cir/src/bin/commands/transmit.rs +++ b/cir/src/bin/commands/transmit.rs @@ -6,7 +6,7 @@ use cir::{ }; use irp::{Irp, Message, Pronto, Vartable}; use log::{error, info, warn}; -use std::{fs, path::Path, str::FromStr}; +use std::{fs, path::Path}; use terminal_size::{terminal_size, Width}; pub fn transmit(transmit: &crate::Transmit) { @@ -229,23 +229,15 @@ fn encode_args(transmit: &crate::Transmit) -> Message { std::process::exit(2); } }, - crate::Transmitables::Scancode(scancode) => { - if let Some((protocol, code)) = scancode.split_once(':') { - match encode_scancode(protocol, code) { - Ok(m) => { - part.push(Part::Raw(m)); - } - Err(msg) => { - error!("{}", msg); - std::process::exit(2); - } + crate::Transmitables::Scancode((protocol, scancode)) => { + match encode_scancode(protocol, *scancode) { + Ok(m) => { + part.push(Part::Raw(m)); + } + Err(msg) => { + error!("{}", msg); + std::process::exit(2); } - } else { - error!( - "{} is not a valid protocol, should be protocol:scancode", - scancode - ); - std::process::exit(2); } } crate::Transmitables::Gap(gap) => { @@ -473,17 +465,7 @@ fn list_lircd_remotes(filename: &Path, remotes: &[lircd_conf::Remote], needle: O } } -fn encode_scancode(protocol: &str, code: &str) -> Result { - let mut scancode = if let Ok(code) = if let Some(hex) = code.strip_prefix("0x") { - u64::from_str_radix(hex, 16) - } else { - u64::from_str(code) - } { - code - } else { - return Err(format!("invalid scancode {code}")); - }; - +fn encode_scancode(protocol: &str, mut scancode: u64) -> Result { let Some(linux) = LinuxProtocol::find_like(protocol) else { return Err(format!("protocol {protocol} is not known")); }; @@ -495,7 +477,7 @@ fn encode_scancode(protocol: &str, code: &str) -> Result { let masked = scancode & linux.scancode_mask as u64; if masked != scancode { - warn!("error: scancode {scancode:#x} masked to {masked:#x}"); + warn!("scancode {scancode:#x} masked to {masked:#x}"); scancode = masked; } diff --git a/cir/tests/encode_tests.rs b/cir/tests/encode_tests.rs index 43a14aa..5a3da19 100644 --- a/cir/tests/encode_tests.rs +++ b/cir/tests/encode_tests.rs @@ -100,6 +100,7 @@ fn encode_rawir_test() { .args([ "transmit", "--dry-run", + "--raw", r#"1000 200 1000"#, @@ -127,9 +128,11 @@ fn encode_rawir_test() { "--dry-run", "-f", "../testdata/rawir/mode2", + "-r", "345", "-g", "30000", + "-r", "+123 40 124", "-g", "40000",