1 use libc::{termios, tcgetattr, tcsetattr};
3 use std::io::{Read, BufRead};
5 use nihav_core::frame::NATimePoint;
7 #[derive(Clone,Copy,Debug,PartialEq)]
24 pub struct CmdLineState {
28 pub fn new() -> Self {
29 let mut orig_state: termios = unsafe { std::mem::MaybeUninit::uninit().assume_init() };
30 unsafe { tcgetattr(0, &mut orig_state); }
31 let mut new_state = orig_state;
32 new_state.c_lflag &= !(libc::ECHO | libc::ICANON);
33 unsafe { tcsetattr(0, 0, &new_state); }
36 pub fn new_normal() -> Self {
37 let mut orig_state: termios = unsafe { std::mem::MaybeUninit::uninit().assume_init() };
38 unsafe { tcgetattr(0, &mut orig_state); }
39 let mut new_state = orig_state;
40 new_state.c_lflag |= libc::ECHO | libc::ICANON;
41 unsafe { tcsetattr(0, 0, &new_state); }
44 pub fn restore(&self) {
45 unsafe { tcsetattr(0, 0, &self.orig_state); }
49 pub fn start_reader() -> (thread::JoinHandle<()>, mpsc::Receiver<Command>) {
50 let (sender, cmd_receiver) = mpsc::sync_channel(100);
51 (thread::spawn(move || {
52 let stdin = std::io::stdin();
53 let mut file = stdin.lock();
54 let mut ch = [0u8; 8];
57 \e char -> alt-char (including alt-[)
58 \e [ char -> A - up B - down C - right D - left F - end H - home (or \e[OF/OH)
60 \e [ num ~ -> 5 - PgUp, 6 - PgDn, 15, 17-24 - F5,F6-F12
62 match file.read(&mut ch) {
65 b'\n' => { sender.send(Command::Next).unwrap(); },
66 b' ' => { sender.send(Command::Pause).unwrap(); },
67 b'q' | b'Q' | 0o33 => {
68 sender.send(Command::Quit).unwrap();
71 b'+' => { sender.send(Command::VolumeUp).unwrap(); },
72 b'-' => { sender.send(Command::VolumeDown).unwrap(); },
73 b'd' | b'D' => { sender.send(Command::Debug).unwrap(); },
74 b'm' | b'M' => { sender.send(Command::Mute).unwrap(); },
76 sender.send(Command::PauseDisplay).unwrap();
77 let cstate = CmdLineState::new_normal();
78 // wait so that the main thread stops displaying
79 thread::sleep(std::time::Duration::from_millis(500));
80 print!("\nJump to: ");
81 let mut str = String::new();
82 let ret = file.read_line(&mut str);
84 sender.send(Command::ResumeDisplay).unwrap();
86 if ret.is_ok() && str.len() > 1 {
88 if let Ok(NATimePoint::Milliseconds(time)) = str.parse::<NATimePoint>() {
89 sender.send(Command::Seek(time)).unwrap();
91 println!("wrong time");
102 b'D' => { sender.send(Command::Back(1)).unwrap(); },
103 b'B' => { sender.send(Command::Back(2)).unwrap(); },
104 b'C' => { sender.send(Command::Forward(1)).unwrap(); },
105 b'A' => { sender.send(Command::Forward(2)).unwrap(); },
106 b'F' => { sender.send(Command::Repeat).unwrap(); },
107 b'H' => { sender.send(Command::Next).unwrap(); },
110 } else if ch[1] == b'O' {
112 b'F' => { sender.send(Command::Repeat).unwrap(); },
113 b'H' => { sender.send(Command::Next).unwrap(); },
120 if ch[0] == 0o33 && ch[1] == b'[' && ch[3] == b'~' {
122 b'5' => { sender.send(Command::Forward(3)).unwrap(); },
123 b'6' => { sender.send(Command::Back(3)).unwrap(); },