aboutsummaryrefslogtreecommitdiffstats
path: root/src/map.rs
blob: cdc5ae17e7a5bde3028ecbe384d97a4e886905e5 (plain)
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
use std::env;
use std::ffi::OsString;
use std::process::Command;

use {Action, HeadphoneButton, MapAction, MapKind};
use ffi::State;
use sounds;

pub enum PlayAudio {
    Yes,
    No,
}

impl PlayAudio {
    fn yes(&self) -> bool {
        match self {
            PlayAudio::Yes => true,
            PlayAudio::No => false,
        }
    }
}

pub fn run_key_action<'a>(
    state: &mut State,
    trigger: &'a [HeadphoneButton],
    play_audio: PlayAudio,
) {
    match state.map_group {
        Some(ref map_group) => {
            let map = map_group.maps.get(trigger);
            let mode = map_group.modes.get(trigger);

            if let Some(in_mode) = state.in_mode.clone() {
                if let Some(mode) = map_group.modes.get(&in_mode) {
                    // Deactivate mode by pressing current mode trigger
                    if &in_mode[..] == trigger {
                        state.in_mode = None;

                        if play_audio.yes() {
                            sounds::play_mode_deactivated().unwrap();
                        }

                        return;
                    }

                    if let Some(map) = mode.get(trigger) {
                        run_action(&map);
                    }
                }
            }

            // TODO: make sure this doesn't run when in_mode
            if state.in_mode.is_none() {
                if let Some(map) = map {
                    run_action(&map);
                }
            }

            if mode.is_some() {
                state.in_mode = Some(trigger.to_vec());

                if play_audio.yes() {
                    sounds::play_mode_activated().unwrap();
                }
            }
        },
        None => (),
    }
}

fn run_action(map_action: &MapAction) {
    match map_action.kind {
        MapKind::Map => {
            if let Action::Map(action) = &map_action.action {
                for key in action {
                    key.tap()
                }
            }
        },
        MapKind::Command => {
            if let Action::String(action) = &map_action.action {
                let shell = match env::var_os("SHELL") {
                    Some(s) => s,
                    None => OsString::from("/bin/sh"),
                };

                match Command::new(shell)
                    .arg("-c")
                    .arg(action)
                    .spawn() {
                    Ok(_) => (),
                    Err(e) => error!(
                        "Command failed to start: `{}'",
                        e
                    ),
                }
            }
        },
    }
}