Skip to content

Instantly share code, notes, and snippets.

@andresilva
Last active February 25, 2020 18:03
Show Gist options
  • Save andresilva/ea9b6d4923c76148058cea7846fb43ab to your computer and use it in GitHub Desktop.
Save andresilva/ea9b6d4923c76148058cea7846fb43ab to your computer and use it in GitHub Desktop.
Motivational USB foot pedal
[package]
name = "motivation-pedal"
version = "0.1.0"
authors = ["André Silva <andre.beat@gmail.com>"]
edition = "2018"
[dependencies]
env_logger = "0.7.1"
hidapi = "1.1.1"
log = "0.4.8"
rand = "0.7.0"
rodio = "0.10.0"
use std::collections::VecDeque;
const VID: u16 = 0x0c45;
const PID: u16 = 0x7404;
fn pressed(buf: &[u8; 8]) -> bool {
*buf == [1, 0, 0, 5, 0, 0, 0, 0]
}
fn random_motivational<'a>(previous: Option<&mut VecDeque<usize>>) -> (&'a str, &'a [u8]) {
use rand::Rng;
macro_rules! sound {
($x:expr) => {
($x, include_bytes!(concat!("../sounds/", $x)))
};
}
const SOUNDS: &[(&str, &[u8])] = &[
sound!("do_it.ogg"),
sound!("dreams2.ogg"),
sound!("dreams.ogg"),
sound!("give_up.ogg"),
sound!("impossible.ogg"),
sound!("just_do_it.ogg"),
sound!("quit.ogg"),
sound!("tomorrow.ogg"),
sound!("waiting.ogg"),
sound!("work.ogg"),
sound!("yes.ogg"),
];
const PREVIOUS_N: usize = 4;
let mut rng = rand::thread_rng();
let index = loop {
let index = rng.gen_range(0, SOUNDS.len());
match previous {
Some(previous) if !previous.contains(&index) => {
while previous.len() >= PREVIOUS_N {
previous.pop_front();
}
previous.push_back(index);
break index;
}
None => break index,
_ => {}
}
};
SOUNDS[index]
}
fn play_random_motivational(
device: &rodio::Device,
previous: Option<&mut VecDeque<usize>>,
) -> Result<rodio::Sink, String> {
use std::io::Cursor;
let (name, data) = random_motivational(previous);
let source = Cursor::new(data);
log::info!("playing: {}", name);
rodio::play_once(device, source).map_err(|err| err.to_string())
}
fn main() -> Result<(), String> {
env_logger::builder()
.filter_level(log::LevelFilter::Info)
.init();
let hid_api = hidapi::HidApi::new().map_err(|err| err.to_string())?;
let usb_device = hid_api.open(VID, PID).map_err(|err| err.to_string())?;
let audio_device = rodio::default_output_device().ok_or("No audio device found.")?;
let mut _audio_sink;
let mut previous = VecDeque::new();
let mut buf = [0u8; 8];
loop {
// blocks until the pedal is pressed/released
let n = usb_device
.read(&mut buf[..])
.map_err(|err| err.to_string())?;
assert_eq!(n, 8);
if pressed(&buf) {
// if the sink is dropped playback stops
_audio_sink = play_random_motivational(&audio_device, Some(&mut previous));
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment