Skip to content

Commit 74e23a5

Browse files
committed
Improved user-friendliness. Closes #7
Every function is now a separate subcommand: * append (append a key, a modifier, or a string to one or more pedals) * clear (clear one or more pedals) * help (print a help message) * list (print a table with all possible keys) * read (read values from the footpedal) * set (set a key or mousebutton to one or more pedals) A disadvantage is that different subcommands cannot be combined in one call of the application anymore. However, this new structure brings the major benefit that the program is more intuitive for users. A second, small change is the fact that the welcome() function now reads application and authore name from the Cargo file.
1 parent dc9def5 commit 74e23a5

4 files changed

Lines changed: 211 additions & 77 deletions

File tree

Cargo.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
[package]
22
name = "footswitch-rs"
33
version = "0.1.0"
4-
authors = ["Dennis <dennis@dennispotter.eu>"]
4+
authors = ["Dennis Potter <dennis@dennispotter.eu>"]
55

66
[dependencies]
7-
structopt = "0.2.10"
7+
structopt = "0.2.13"
88
hidapi = "0.5.0"
9-
users = "0.7"
9+
users = "0.8"
1010
colored = "1.6.1"
1111

src/main.rs

Lines changed: 184 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -20,32 +20,43 @@ use colored::*;
2020
#[derive(StructOpt, Debug)]
2121
#[structopt(name = "rust-footswitch")]
2222
struct Opt {
23-
/// Prints a table of all keys with <listkeys> rows
24-
#[structopt(short = "l", long = "listkeys")]
25-
listkeys: Option<usize>,
26-
2723
#[structopt(subcommand)]
2824
cmd: Option<Command>,
2925
}
3026

3127
#[derive(StructOpt, Debug)]
3228
enum Command {
33-
/// Write to the footpedal
34-
#[structopt(name = "write")]
35-
Write {
36-
/// Specify pedal to modify with following command. Possible values: [0 | 1 | 2]
37-
#[structopt(short = "p", long = "pedal")]
38-
pedal: Vec<u8>,
29+
/// Prints a table of all possible keys
30+
#[structopt(name = "list")]
31+
ListKeys {
32+
/// Specify the number of columns of the table
33+
#[structopt(short = "c", long = "columns")]
34+
columns: usize,
35+
},
3936

40-
/// Command to apply. Possible values: [set_key | set_mousebutton | del_key | app_key | app_str | app_mod]
41-
#[structopt(short = "c", long = "command")]
42-
command: Vec<String>,
37+
/// Set a key or a mousebutton to one or more pedals
38+
#[structopt(name = "set")]
39+
Set {
40+
#[structopt(subcommand)]
41+
cmd: Set
42+
},
4343

44-
/// Input values to apply
45-
#[structopt(short = "i", long = "input")]
46-
input: Vec<String>,
44+
/// Append a key, a modifier, or a string to one or more pedals
45+
#[structopt(name = "append")]
46+
Append {
47+
#[structopt(subcommand)]
48+
cmd: Append
4749
},
4850

51+
/// Clear the value of one or more pedals
52+
#[structopt(name = "clear")]
53+
Clear {
54+
/// Specify pedal(s) to clear: [0 | 1 | 2]
55+
#[structopt(short = "p", long = "pedal")]
56+
pedal: Vec<u8>,
57+
},
58+
59+
/// Read from the footpedal
4960
#[structopt(name = "read")]
5061
Read {
5162
/// Read all pedals
@@ -58,76 +69,180 @@ enum Command {
5869
}
5970
}
6071

72+
#[derive(StructOpt, Debug)]
73+
enum Set {
74+
/// Set a key value to one or more pedals
75+
#[structopt(name = "key")]
76+
SetKey {
77+
/// Specify pedal(s) to modify: [0 | 1 | 2]
78+
#[structopt(short = "p", long = "pedal")]
79+
pedal: Vec<u8>,
80+
81+
/// Value(s) to apply
82+
#[structopt(short = "i", long = "input")]
83+
input: Vec<String>,
84+
},
85+
86+
/// Set a mousebutton to one or more pedals
87+
#[structopt(name = "mousebutton")]
88+
SetMousebutton {
89+
/// Specify pedal(s) to modify: [0 | 1 | 2]
90+
#[structopt(short = "p", long = "pedal")]
91+
pedal: Vec<u8>,
92+
93+
/// Value(s) to apply
94+
#[structopt(short = "i", long = "input")]
95+
input: Vec<String>,
96+
},
97+
98+
/// Set X, Y, and W movement of the mouse pointer for one or more pedals
99+
#[structopt(name = "mousemovement")]
100+
SetMousemovement {
101+
/// Specify pedal(s) to modify: [0 | 1 | 2]
102+
#[structopt(short = "p", long = "pedal")]
103+
pedal: Vec<u8>,
104+
105+
/// X value(s): [-128,127]
106+
#[structopt(short = "x")]
107+
x: Vec<i8>,
108+
109+
/// Y value(s): [-128,127]
110+
#[structopt(short = "y")]
111+
y: Vec<i8>,
112+
113+
/// W value(s): [-128,127]
114+
#[structopt(short = "w")]
115+
w: Vec<i8>,
116+
}
117+
}
118+
119+
#[derive(StructOpt, Debug)]
120+
enum Append {
121+
/// Append a key value to one or more pedals
122+
#[structopt(name = "key")]
123+
AppendKey {
124+
/// Specify pedal(s) to modify: [0 | 1 | 2]
125+
#[structopt(short = "p", long = "pedal")]
126+
pedal: Vec<u8>,
127+
128+
/// Value(s) to apply
129+
#[structopt(short = "i", long = "input")]
130+
input: Vec<String>,
131+
},
132+
133+
/// Append a string to one or more pedals
134+
#[structopt(name = "string")]
135+
AppendString {
136+
/// Specify pedal(s) to modify: [0 | 1 | 2]
137+
#[structopt(short = "p", long = "pedal")]
138+
pedal: Vec<u8>,
139+
140+
/// Value(s) to apply
141+
#[structopt(short = "i", long = "input")]
142+
input: Vec<String>,
143+
},
144+
145+
/// Append a modifier to one or more pedals
146+
#[structopt(name = "modifier")]
147+
AppendModifier {
148+
/// Specify pedal(s) to modify: [0 | 1 | 2]
149+
#[structopt(short = "p", long = "pedal")]
150+
pedal: Vec<u8>,
151+
152+
/// Value(s) to apply
153+
#[structopt(short = "i", long = "input")]
154+
input: Vec<String>,
155+
}
156+
}
157+
61158
fn main() {
62159
let opt = Opt::from_args();
63160

64-
welcome("footswitch-rs, Dennis Potter <dennis@dennispotter.eu>");
161+
welcome();
65162
check_sudo();
66-
67-
163+
68164
// All options that don't need the device to be open
69165
// Print all keys and exit application
70-
if let Some(x) = opt.listkeys {
71-
key_operations::print_key_map(x);
72-
goodbye();
166+
match opt.cmd {
167+
Some(Command::ListKeys { columns }) => {
168+
key_operations::print_key_map(columns);
169+
goodbye();
170+
},
171+
_ => { /* Do nothing, there are still lots of other options further below */ }
73172
}
74173

75174
let mut pedals = pedal_operations::Pedals::new();
76175

77-
78-
79176
// All options that need the device to be open
80177
match opt.cmd {
81-
Some(Command::Write {pedal: ped_list, command: cmd_list, input: val_list}) => {
82-
if ped_list.len() != cmd_list.len() && ped_list.len() != val_list.len() {
83-
error!("You must define as much pedals as you define commands and as you define input values!");
84-
}
178+
Some(Command::Append { cmd }) => {
179+
match cmd {
180+
Append::AppendKey { pedal, input } =>
181+
{
85182

86-
for (i, cmd) in cmd_list.iter().enumerate() {
87-
match cmd as &str {
88-
"set_key" => {
89-
pedals.set_key(ped_list[i] as usize, val_list[i].as_str());
90-
}
91-
"set_mousebutton" => {
92-
pedals.set_mousebutton(ped_list[i] as usize, val_list[i].as_str());
93-
}
94-
"del_key" => {
95-
}
96-
"app_key" => {
97-
}
98-
"app_str" => {
99-
pedals.set_string(ped_list[i] as usize, val_list[i].as_str());
183+
},
184+
Append::AppendString { pedal, input } =>
185+
{
186+
check_length(&pedal, &input);
187+
188+
for (i, pedal) in pedal.iter().enumerate() {
189+
pedals.set_string(*pedal as usize, input[i].as_str());
100190
}
101-
"app_mod" => {
102-
pedals.set_modifier(ped_list[i] as usize, val_list[i].as_str());
191+
},
192+
Append::AppendModifier { pedal, input } =>
193+
{
194+
check_length(&pedal, &input);
195+
196+
for (i, pedal) in pedal.iter().enumerate() {
197+
pedals.set_modifier(*pedal as usize, input[i].as_str());
103198
}
104-
"set_x" => {
105-
pedals.set_mouse_xyw(ped_list[i] as usize, val_list[i].as_str(), 5)
199+
}
200+
}
201+
202+
pedals.update_and_close();
203+
},
204+
205+
Some(Command::Set { cmd }) => {
206+
match cmd {
207+
Set::SetKey { pedal, input } =>
208+
{
209+
check_length(&pedal, &input);
210+
211+
for (i, pedal) in pedal.iter().enumerate() {
212+
pedals.set_key(*pedal as usize, input[i].as_str());
106213
}
107-
"set_y" => {
108-
pedals.set_mouse_xyw(ped_list[i] as usize, val_list[i].as_str(), 6)
214+
},
215+
Set::SetMousebutton { pedal, input } =>
216+
{
217+
check_length(&pedal, &input);
218+
219+
for (i, pedal) in pedal.iter().enumerate() {
220+
pedals.set_mousebutton(*pedal as usize, input[i].as_str());
109221
}
110-
"set_w" => {
111-
pedals.set_mouse_xyw(ped_list[i] as usize, val_list[i].as_str(), 7)
222+
}
223+
224+
Set::SetMousemovement { pedal, x, y, w } =>
225+
{
226+
227+
if pedal.len() != x.len() || x.len() != y.len() || y.len() != w.len() {
228+
error!("You must define X, Y, and W for every pedal. If a direction is not needed, set it to 0!");
112229
}
113-
_ => {
114-
error!("Unknown command!");
230+
231+
for (i, pedal) in pedal.iter().enumerate() {
232+
pedals.set_mouse_xyw(*pedal as usize, x[i], 5);
233+
pedals.set_mouse_xyw(*pedal as usize, y[i], 6);
234+
pedals.set_mouse_xyw(*pedal as usize, w[i], 7);
115235
}
116236
}
117237
}
118238

119-
// Since we ran the Write command without any errors, we are now writing everything
120-
pedals.write_pedals();
121-
122-
info!("Successfully wrote everything to footpedal!");
123-
info!("The current state of the device is shown below.");
124-
125-
// Show user current state of pedal
126-
pedals.read_pedals(vec![0,1,2]);
239+
pedals.update_and_close();
240+
},
127241

128-
goodbye();
242+
Some(Command::Clear { pedal }) => {
129243

130244
},
245+
131246
Some(Command::Read {all: all_var, pedals: ped_list}) => {
132247
if ped_list.len() > 3 {
133248
error!("Number of pedals may not be bigger than 3!");
@@ -145,6 +260,8 @@ fn main() {
145260

146261
goodbye();
147262
},
263+
264+
Some(Command::ListKeys { columns:_columns }) => { /* This case will never occur */ },
148265
None => {
149266
error!("You did not specify any command. Run './footswitch-rs --help' for more information.");
150267
}
@@ -157,3 +274,9 @@ fn check_sudo() {
157274
error!("Please execute this application as super user!");
158275
}
159276
}
277+
278+
fn check_length(pedal: & Vec<u8>, input: & Vec<String>) {
279+
if pedal.len() != input.len() {
280+
error!("You must define as much pedals as you define input values!");
281+
}
282+
}

src/messages.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,15 @@ macro_rules! error {
2626
};
2727
}
2828

29-
pub fn welcome(string: &str) {
30-
println!("┌{}┐", "─".repeat(string.len() + 20));
31-
println!("│{text:^-width$}│", text = string, width = string.len() + 20);
32-
println!("├{}┘", "─".repeat(string.len() + 20));
29+
pub fn welcome() {
30+
const AUTHORS: &'static str = env!("CARGO_PKG_AUTHORS");
31+
const NAME: &'static str = env!("CARGO_PKG_NAME");
32+
33+
let name_authors = &[NAME, " | ", AUTHORS].concat();
34+
35+
println!("┌{}┐", "─".repeat(name_authors.len() + 20));
36+
println!("│{text:^-width$}│", text = name_authors, width = name_authors.len() + 20);
37+
println!("├{}┘", "─".repeat(name_authors.len() + 20));
3338
}
3439

3540
pub fn goodbye() {

src/pedal_operations.rs

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ extern crate hidapi;
44
use std::process;
55
use std::ffi::CString;
66
use colored::*;
7+
use messages::*;
78

89
#[derive(Copy, Clone)]
910
enum Type {
@@ -285,20 +286,12 @@ impl Pedals {
285286
self.ped_data[ped].data[4] |= mousebutton as u8;
286287
}
287288

288-
pub fn set_mouse_xyw(& mut self, ped:usize, value:&str, direction:usize) {
289+
pub fn set_mouse_xyw(& mut self, ped:usize, value_i8:i8, direction:usize) {
289290
// The values of the directions match the array index of ped_data[].data[]
290291
// X = 5
291292
// Y = 6
292293
// W = 7
293294

294-
// Translate value passed by user to integer
295-
let value_i8 = match value.parse::<i8>() {
296-
Ok(x) => x,
297-
Err(x) => {
298-
error!("The value of {} ({}) must be in [-128, 127]! Message: {}.", direction, value, x)
299-
}
300-
};
301-
302295
// Translate to u8
303296
let mut value_u8 = value_i8 as u8;
304297

@@ -372,4 +365,17 @@ impl Pedals {
372365

373366

374367
}
368+
369+
/// Update device and close application
370+
pub fn update_and_close(& mut self) {
371+
self.write_pedals();
372+
373+
info!("Successfully wrote everything to footpedal!");
374+
info!("The current state of the device is shown below.");
375+
376+
// Show user current state of pedal
377+
self.read_pedals(vec![0,1,2]);
378+
379+
goodbye();
380+
}
375381
}

0 commit comments

Comments
 (0)