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
|
use std::env;
use std::ffi::OsString;
use std::process::Command;
use {Action, HeadphoneButton, MapAction, MapKind};
use errors::*;
use ffi::State;
#[repr(C)]
pub enum ModeChange {
Activated,
Deactivated,
}
pub fn run_key_action<'a>(
state: &mut State,
trigger: &'a [HeadphoneButton],
on_mode_change: extern "C" fn(mode_change: ModeChange),
) -> Result<()> {
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;
on_mode_change(ModeChange::Deactivated);
return Ok(());
}
if let Some(map) = mode.get(trigger) {
run_action(&map)?;
}
}
}
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());
on_mode_change(ModeChange::Activated);
}
},
None => (),
};
Ok(())
}
fn run_action(map_action: &MapAction) -> Result<()> {
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"),
};
return Command::new(shell)
.arg("-c")
.arg(action)
.spawn()
.map(|_| ())
.chain_err(|| "command failed to start");
}
},
};
Ok(())
}
|