add nihav-sndplay
[nihav-player.git] / sndplay / src / command.rs
diff --git a/sndplay/src/command.rs b/sndplay/src/command.rs
new file mode 100644 (file)
index 0000000..802908b
--- /dev/null
@@ -0,0 +1,101 @@
+use libc::{termios, tcgetattr, tcsetattr};
+use std::sync::mpsc;
+use std::io::Read;
+use std::thread;
+
+#[derive(Clone,Copy,Debug,PartialEq)]
+pub enum Command {
+    Debug,
+    Mute,
+    VolumeUp,
+    VolumeDown,
+    Pause,
+    Back(u8),
+    Forward(u8),
+    Repeat,
+    Next,
+    Quit,
+}
+
+pub struct CmdLineState {
+    orig_state: termios
+}
+impl CmdLineState {
+    pub fn new() -> Self {
+        let mut orig_state: termios = unsafe { std::mem::uninitialized() };
+        unsafe { tcgetattr(0, &mut orig_state); }
+        let mut new_state = orig_state;
+        new_state.c_lflag &= !(libc::ECHO | libc::ICANON);
+        unsafe { tcsetattr(0, 0, &new_state); }
+        Self { orig_state }
+    }
+    pub fn restore(&self) {
+        unsafe { tcsetattr(0, 0, &self.orig_state); }
+    }
+}
+
+pub fn start_reader() -> (thread::JoinHandle<()>, mpsc::Receiver<Command>) {
+    let (sender, cmd_receiver) = mpsc::sync_channel(100);
+    (thread::spawn(move || {
+        let stdin = std::io::stdin();
+        let mut file = stdin.lock();
+        let mut ch = [0u8; 8];
+        loop {
+/*
+\e char -> alt-char (including alt-[)
+\e [ char -> A - up B - down C - right D - left F - end H - home (or \e[OF/OH)
+\e [ O P-S -> F1-F4
+\e [ num ~ -> 5 - PgUp, 6 - PgDn, 15, 17-24 - F5,F6-F12
+*/
+            match file.read(&mut ch) {
+                Ok(1) => {
+                    match ch[0] {
+                        b'\n' => { sender.send(Command::Next).unwrap(); },
+                        b' ' => { sender.send(Command::Pause).unwrap(); },
+                        b'q' | b'Q' | 0o33 => {
+                            sender.send(Command::Quit).unwrap();
+                            break;
+                        },
+                        b'+' => { sender.send(Command::VolumeUp).unwrap(); },
+                        b'-' => { sender.send(Command::VolumeDown).unwrap(); },
+                        b'd' | b'D' => { sender.send(Command::Debug).unwrap(); },
+                        b'm' | b'M' => { sender.send(Command::Mute).unwrap(); },
+                        _ => {},
+                    };
+                },
+                Ok(3) => {
+                    if ch[0] == 0o33 {
+                        if ch[1] == b'[' {
+                            match ch[2] {
+                                b'D' => { sender.send(Command::Back(1)).unwrap(); },
+                                b'B' => { sender.send(Command::Back(2)).unwrap(); },
+                                b'C' => { sender.send(Command::Forward(1)).unwrap(); },
+                                b'A' => { sender.send(Command::Forward(2)).unwrap(); },
+                                b'F' => { sender.send(Command::Repeat).unwrap(); },
+                                b'H' => { sender.send(Command::Next).unwrap(); },
+                                _ => {},
+                            };
+                        } else if ch[1] == b'O' {
+                            match ch[2] {
+                                b'F' => { sender.send(Command::Repeat).unwrap(); },
+                                b'H' => { sender.send(Command::Next).unwrap(); },
+                                _ => {},
+                            };
+                        }
+                    }
+                },
+                Ok(4) => {
+                    if ch[0] == 0o33 && ch[1] == b'[' && ch[3] == b'~' {
+                        match ch[2] {
+                            b'5' => { sender.send(Command::Forward(3)).unwrap(); },
+                            b'6' => { sender.send(Command::Back(3)).unwrap(); },
+                            _ => {},
+                        };
+                    }
+                },
+                Ok(_) => {},
+                Err(_) => break,
+            }
+        }
+    }), cmd_receiver)
+}
\ No newline at end of file