summaryrefslogtreecommitdiffstats
path: root/sndplay/src/command.rs
blob: 802908b2de0e0ec818c8eed2e8bed4c9dfd662cd (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
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)
}