2018-07-10 21:41:58 +00:00
|
|
|
//! Footswitch-RS
|
|
|
|
//!
|
|
|
|
//! `footswitch-rs` enables you to use footswitches of <xxx>
|
2018-07-26 15:15:39 +00:00
|
|
|
//!
|
2018-07-26 16:20:53 +00:00
|
|
|
pub mod key_operations;
|
|
|
|
pub mod pedal_operations;
|
2018-07-10 21:41:58 +00:00
|
|
|
|
2018-07-26 15:15:39 +00:00
|
|
|
#[macro_use]
|
|
|
|
mod messages;
|
|
|
|
|
2018-07-10 21:41:58 +00:00
|
|
|
#[macro_use]
|
|
|
|
extern crate structopt;
|
|
|
|
extern crate hidapi;
|
|
|
|
extern crate users;
|
2018-07-26 15:15:39 +00:00
|
|
|
extern crate colored;
|
2018-07-10 21:41:58 +00:00
|
|
|
|
2018-07-11 10:02:10 +00:00
|
|
|
use std::process;
|
2018-07-10 21:41:58 +00:00
|
|
|
use structopt::StructOpt;
|
2018-07-26 15:15:39 +00:00
|
|
|
use messages::*;
|
|
|
|
use colored::*;
|
2018-07-10 21:41:58 +00:00
|
|
|
|
|
|
|
#[derive(StructOpt, Debug)]
|
|
|
|
#[structopt(name = "rust-footswitch")]
|
|
|
|
struct Opt {
|
|
|
|
/// Prints a table of all keys with <listkeys> rows
|
|
|
|
#[structopt(short = "l", long = "listkeys")]
|
2018-07-11 10:02:10 +00:00
|
|
|
listkeys: Option<usize>,
|
2018-07-10 21:41:58 +00:00
|
|
|
|
2018-07-25 22:35:25 +00:00
|
|
|
#[structopt(subcommand)]
|
|
|
|
cmd: Option<Command>,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(StructOpt, Debug)]
|
|
|
|
enum Command {
|
|
|
|
/// Write to the footpedal
|
|
|
|
#[structopt(name = "write")]
|
|
|
|
Write {
|
|
|
|
/// Specify pedal to modify with following command. Possible values: [0 | 1 | 2]
|
|
|
|
#[structopt(short = "p", long = "pedal")]
|
|
|
|
pedal: Vec<u8>,
|
|
|
|
|
|
|
|
/// Command to apply. Possible values: [set_key | del_key | append_key | append_str]
|
|
|
|
#[structopt(short = "c", long = "command")]
|
|
|
|
command: Vec<String>,
|
|
|
|
|
2018-07-26 16:44:28 +00:00
|
|
|
/// Input values to apply
|
|
|
|
#[structopt(short = "i", long = "input")]
|
|
|
|
input: Vec<String>,
|
2018-07-25 22:35:25 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
#[structopt(name = "read")]
|
|
|
|
Read {
|
|
|
|
/// Read all pedals
|
|
|
|
#[structopt(short = "a", long = "all")]
|
|
|
|
all: bool,
|
|
|
|
|
|
|
|
/// Specify specific pedals. Possible values: [0 | 1 | 2]
|
|
|
|
#[structopt(short = "p", long = "pedal")]
|
|
|
|
pedals: Vec<u8>,
|
|
|
|
}
|
2018-07-10 21:41:58 +00:00
|
|
|
}
|
|
|
|
|
2018-07-10 21:36:20 +00:00
|
|
|
fn main() {
|
2018-07-24 17:03:35 +00:00
|
|
|
let mut pedals = pedal_operations::Pedals::new();
|
2018-07-26 15:15:39 +00:00
|
|
|
|
2018-07-26 16:44:28 +00:00
|
|
|
let opt = Opt::from_args();
|
|
|
|
|
2018-07-26 15:15:39 +00:00
|
|
|
welcome("footswitch-rs, Dennis Potter <dennis@dennispotter.eu>");
|
2018-07-10 21:41:58 +00:00
|
|
|
check_sudo();
|
|
|
|
|
|
|
|
|
2018-07-11 10:02:10 +00:00
|
|
|
// All options that don't need the device to be open
|
|
|
|
// Print all keys and exit application
|
|
|
|
if let Some(x) = opt.listkeys {
|
|
|
|
key_operations::print_key_map(x);
|
2018-07-26 15:15:39 +00:00
|
|
|
goodbye();
|
2018-07-11 10:02:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Open device
|
2018-07-23 22:16:28 +00:00
|
|
|
// This is the reason, the device is not part of the struct: https://github.com/Osspial/hidapi-rs/issues/16
|
|
|
|
// Maybe this can be fixed, as soon as this is merged into the crate: https://github.com/Osspial/hidapi-rs/pull/12
|
2018-07-10 21:41:58 +00:00
|
|
|
let vld_dev = [
|
|
|
|
(0x0c45u16, 0x7403u16),
|
|
|
|
(0x0c45 , 0x7404),
|
|
|
|
(0x413d , 0x2107)
|
|
|
|
];
|
|
|
|
|
2018-07-27 21:43:24 +00:00
|
|
|
info!("Initializing HID object. This can take a moment.");
|
|
|
|
|
|
|
|
let api = match hidapi::HidApi::new() {
|
|
|
|
Ok(res) => {
|
|
|
|
info!("Succesfully initialized HID object.");
|
|
|
|
res
|
|
|
|
},
|
|
|
|
Err(_) => {
|
|
|
|
error!("Could not initialize HID object.")
|
|
|
|
},
|
|
|
|
};
|
2018-07-26 15:15:39 +00:00
|
|
|
|
2018-07-11 10:02:10 +00:00
|
|
|
let mut dev_path = String::new();
|
|
|
|
|
|
|
|
for device in &api.devices() {
|
|
|
|
for val in vld_dev.iter() {
|
|
|
|
if *val == (device.vendor_id, device.product_id) && device.interface_number == 1 {
|
2018-07-26 15:15:39 +00:00
|
|
|
info!("Found device {:x}:{:x} ({})", device.vendor_id, device.product_id, device.path);
|
2018-07-11 10:02:10 +00:00
|
|
|
dev_path = device.path.clone();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-07-27 21:43:24 +00:00
|
|
|
|
|
|
|
let dev = match api.open_path(dev_path.as_str()) {
|
|
|
|
Ok(res) => {
|
|
|
|
info!("Succesfully opened device.");
|
|
|
|
res
|
|
|
|
},
|
|
|
|
Err(_) => {
|
|
|
|
error!("Could not open device. Make sure your device is connected. Maybe try to reconnect it.")
|
|
|
|
},
|
|
|
|
};
|
2018-07-10 21:41:58 +00:00
|
|
|
|
2018-07-24 17:03:35 +00:00
|
|
|
|
2018-07-11 10:02:10 +00:00
|
|
|
// All options that need the device to be open
|
2018-07-25 22:35:25 +00:00
|
|
|
match opt.cmd {
|
2018-07-26 16:44:28 +00:00
|
|
|
Some(Command::Write {pedal: ped_list, command: cmd_list, input: val_list}) => {
|
2018-07-25 22:35:25 +00:00
|
|
|
if ped_list.len() != cmd_list.len() && ped_list.len() != val_list.len() {
|
2018-07-26 16:44:28 +00:00
|
|
|
error!("You must define as much pedals as you define commands and as you define input values!");
|
2018-07-25 22:35:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for (i, cmd) in cmd_list.iter().enumerate() {
|
|
|
|
match cmd as &str {
|
2018-07-30 22:34:35 +00:00
|
|
|
"set_key" => {
|
|
|
|
pedals.set_key(ped_list[i] as usize, val_list[i].as_str());
|
2018-07-25 22:35:25 +00:00
|
|
|
}
|
|
|
|
"del_key" => {
|
|
|
|
}
|
|
|
|
"append_key" => {
|
|
|
|
}
|
|
|
|
"append_str" => {
|
2018-07-30 22:34:35 +00:00
|
|
|
pedals.set_string(ped_list[i] as usize, val_list[i].as_str());
|
2018-07-25 22:35:25 +00:00
|
|
|
}
|
|
|
|
_ => {
|
2018-07-26 15:15:39 +00:00
|
|
|
error!("Unkonwn command!");
|
2018-07-25 22:35:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-07-26 15:15:39 +00:00
|
|
|
|
2018-07-25 22:35:25 +00:00
|
|
|
// Since we ran the Write command without any errors, we are now writing everything
|
|
|
|
pedals.write_pedals(& dev);
|
|
|
|
|
2018-07-26 15:15:39 +00:00
|
|
|
info!("Succesfully wrote everything to footpedal!");
|
2018-07-26 16:44:28 +00:00
|
|
|
info!("The current state of the device is shown below.");
|
2018-07-25 22:35:25 +00:00
|
|
|
|
|
|
|
// Show user current state of pedal
|
2018-07-26 15:15:39 +00:00
|
|
|
pedals.read_pedals(&dev, vec![0,1,2]);
|
|
|
|
|
|
|
|
goodbye();
|
2018-07-25 22:35:25 +00:00
|
|
|
|
|
|
|
},
|
|
|
|
Some(Command::Read {all: all_var, pedals: ped_list}) => {
|
|
|
|
if ped_list.len() > 3 {
|
2018-07-26 15:15:39 +00:00
|
|
|
error!("Number of pedals may not be bigger than 3!");
|
2018-07-25 22:35:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if all_var {
|
|
|
|
pedals.read_pedals(&dev, vec![0,1,2]);
|
|
|
|
}
|
|
|
|
else if ped_list.len() > 0 {
|
|
|
|
pedals.read_pedals(&dev, ped_list)
|
|
|
|
}
|
|
|
|
else {
|
2018-07-26 15:15:39 +00:00
|
|
|
error!("You did not specify any command. Run './footswitch-rs read --help' for more information");
|
2018-07-25 22:35:25 +00:00
|
|
|
}
|
2018-07-26 15:15:39 +00:00
|
|
|
|
|
|
|
goodbye();
|
|
|
|
},
|
|
|
|
None => {
|
|
|
|
error!("You did not specify any command. Run './footswitch-rs --help' for more information.");
|
2018-07-25 22:35:25 +00:00
|
|
|
}
|
2018-07-23 21:52:10 +00:00
|
|
|
}
|
2018-07-10 21:41:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Checks if user is super user
|
|
|
|
fn check_sudo() {
|
|
|
|
if users::get_current_uid() != 0 {
|
2018-07-26 15:15:39 +00:00
|
|
|
error!("Please execute this application as super user!");
|
2018-07-10 21:41:58 +00:00
|
|
|
}
|
|
|
|
}
|