use serial::SerialPort; use walkdir::WalkDir; fn main() { let helptext = "Argument 1 is serial port (for example /dev/ttyACM0, Argument 2 is the directory with the music, no stars."; let mut args = std::env::args_os(); let _selfname = args.next(); let serialport = args.next().expect(helptext); let musicdir = args.next().expect(helptext); println!("opening serial port"); let mut port = serial::open(&serialport).expect("could not open serial port"); port.reconfigure(&|settings| { settings.set_baud_rate(serial::Baud115200)?; settings.set_char_size(serial::Bits8); settings.set_parity(serial::ParityNone); settings.set_stop_bits(serial::Stop1); settings.set_flow_control(serial::FlowNone); Ok(()) }) .expect("could not configure port"); port.set_timeout(std::time::Duration::from_secs(30)) .expect("could not set timeout"); println!("serial port opened"); println!("skimming music dir"); let walker = WalkDir::new(musicdir).into_iter(); let walker = walker.filter_entry(|e| { e.file_name() .to_str() .map(|s| !s.starts_with('.')) .unwrap_or(true) }); let mut music = Vec::new(); for entry in walker { match entry { Err(e) => eprintln!("error when reading music dir, continuing: {:?}", e), Ok(entry) => { if entry.file_type().is_file() && entry.path().extension() != Some(std::ffi::OsStr::new("jpg")){ music.push(entry.path().to_owned()); } } } } println!("music dir skimmed"); use rand::seq::SliceRandom; use rand::SeedableRng; let mut rng = rand::rngs::SmallRng::seed_from_u64(0); music.shuffle(&mut rng); println!("loaded {} \"songs\"", music.len()); /* for i in (0..music.len()).rev() { enum Err{ Empty, File, } let c = || -> Result<(), Err> { // we might run out of music cause we are deliting inline, this is fine. let choice = &music.get(i).ok_or(Err::Empty)?; let f = std::fs::File::open(&choice).map_err(|_| Err::File)?; let rdr = BufReader::new(f); let _d = rodio::Decoder::new(rdr).map_err(|_| Err::File)?; Ok(()) }; match (c)() { Err(Err::File) => {dbg!(music.remove(i));}, _ => (), } } */ println!("checked all songs"); println!("opening audio output"); let (_stream, stream_handle) = rodio::OutputStream::try_default() .expect("could not open audio output, or could not find any"); let mut sink = rodio::Sink::try_new(&stream_handle).expect("could not create sink"); println!("audio output opened"); use std::io::BufRead; use std::io::BufReader; let mut port = BufReader::new(port); // wage has valid range 0-5000 let mut max: usize = 5000; let mut preval = 0; let mut prechoice = 0; let mut readbuf = String::new(); let mut n_changed = 0; use std::io::Write; port.get_mut().write(b"r").unwrap(); loop { readbuf.clear(); port.read_line(&mut readbuf).unwrap(); //println!("got line: {}", readbuf); let err = "got invalid message from wage"; let w: usize = readbuf.trim().parse().expect(err); if w == 8888 || w == 69_69_69_69 { // special values: 8888 and 69696969 // are turned off and EEEE } else { max = max.max(w); let choice = (w * (music.len() - 1)) / max; let absdiff = w.max(preval) - w.min(preval); if absdiff > 1 && choice != prechoice { n_changed += 1; } else { n_changed = 0; } if n_changed >= 7 { let choicef = &music[(music.len() - 1) - choice]; println!("changing song to {:?}", choicef); let mut c = || -> Result<(), ()> { let f = std::fs::File::open(choicef).map_err(|_| ())?; let rdr = BufReader::new(f); let d = rodio::Decoder::new(rdr).map_err(|_| ())?; //let s = rodio::source::SineWave::new(440); let newsink = rodio::Sink::try_new(&stream_handle).expect("could not create sink"); newsink.append(d); sink.stop(); sink = newsink; Ok(()) }; if let Err(_error) = (c)() { println!("music was not music"); let r = music.remove((music.len() - 1) - choice); println!("removed {:?}", r); } else { preval = w; prechoice = choice; n_changed = 0; } } } std::thread::sleep(std::time::Duration::from_millis(100)); port.get_mut().write(b"r").unwrap(); } }