diff --git a/Cargo.lock b/Cargo.lock index f8c1903..a45187e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,5 +1,15 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +[[package]] +name = "alsa-sys" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0edcbbf9ef68f15ae1b620f722180b82a98b6f0628d30baa6b8d2a5abc87d58" +dependencies = [ + "libc", + "pkg-config", +] + [[package]] name = "arrayref" version = "0.3.6" @@ -24,12 +34,38 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff" +[[package]] +name = "bindgen" +version = "0.53.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c72a978d268b1d70b0e963217e60fdabd9523a941457a6c42a7315d15c7e89e5" +dependencies = [ + "bitflags 1.2.1", + "cexpr", + "cfg-if", + "clang-sys", + "lazy_static", + "lazycell", + "peeking_take_while", + "proc-macro2", + "quote 1.0.7", + "regex", + "rustc-hash", + "shlex", +] + [[package]] name = "bitflags" version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5" +[[package]] +name = "bitflags" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" + [[package]] name = "blake2b_simd" version = "0.5.10" @@ -47,12 +83,27 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" +[[package]] +name = "byteorder" +version = "1.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" + [[package]] name = "cc" version = "1.0.59" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "66120af515773fb005778dc07c261bd201ec8ce50bd6e7144c927753fe013381" +[[package]] +name = "cexpr" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4aedb84272dbe89af497cf81375129abda4fc0a9e7c5d317498c15cc30c0d27" +dependencies = [ + "nom", +] + [[package]] name = "cfg-if" version = "0.1.10" @@ -70,12 +121,71 @@ dependencies = [ "time", ] +[[package]] +name = "clang-sys" +version = "0.29.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe6837df1d5cba2397b835c8530f51723267e16abbf83892e9e5af4f0e5dd10a" +dependencies = [ + "glob", + "libc", + "libloading", +] + +[[package]] +name = "claxon" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bfbf56724aa9eca8afa4fcfadeb479e722935bb2a0900c2d37e0cc477af0688" + [[package]] name = "constant_time_eq" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" +[[package]] +name = "core-foundation-sys" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b" + +[[package]] +name = "coreaudio-rs" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f229761965dad3e9b11081668a6ea00f1def7aa46062321b5ec245b834f6e491" +dependencies = [ + "bitflags 1.2.1", + "coreaudio-sys", +] + +[[package]] +name = "coreaudio-sys" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6570ee6e089131e928d5ec9236db9e818aa3cf850f48b0eec6ef700571271d4" +dependencies = [ + "bindgen", +] + +[[package]] +name = "cpal" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b55d55d69f403f62a95bd3c04b431e0aedf5120c70f15d07a8edd234443dd59" +dependencies = [ + "alsa-sys", + "core-foundation-sys", + "coreaudio-rs", + "lazy_static", + "libc", + "num-traits", + "stdweb", + "thiserror", + "winapi", +] + [[package]] name = "crossbeam-utils" version = "0.7.2" @@ -97,6 +207,15 @@ dependencies = [ "libdbus-sys", ] +[[package]] +name = "directories" +version = "3.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8fed639d60b58d0f53498ab13d26f621fd77569cc6edb031f4cc36a2ad9da0f" +dependencies = [ + "dirs-sys", +] + [[package]] name = "dirs" version = "1.0.5" @@ -108,11 +227,25 @@ dependencies = [ "winapi", ] +[[package]] +name = "dirs-sys" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e93d7f5705de3e49895a2b5e0b8855a1c27f080192ae9c32a6432d50741a57a" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + [[package]] name = "domasi" version = "0.1.0" dependencies = [ + "directories", + "lazy_static", "notify-rust", + "rodio", ] [[package]] @@ -126,12 +259,41 @@ dependencies = [ "wasi 0.9.0+wasi-snapshot-preview1", ] +[[package]] +name = "glob" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" + +[[package]] +name = "hound" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a164bb2ceaeff4f42542bdb847c41517c78a60f5649671b2a07312b6e117549" + [[package]] name = "lazy_static" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + +[[package]] +name = "lewton" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be42bea7971f4ba0ea1e215730c29bc1ff9bd2a9c10013912f42a8dcf8d77c0d" +dependencies = [ + "byteorder", + "ogg", + "tinyvec", +] + [[package]] name = "libc" version = "0.2.76" @@ -147,6 +309,16 @@ dependencies = [ "pkg-config", ] +[[package]] +name = "libloading" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2b111a074963af1d37a139918ac6d49ad1d0d5e47f72fd55388619691a7d753" +dependencies = [ + "cc", + "winapi", +] + [[package]] name = "mac-notification-sys" version = "0.3.0" @@ -159,6 +331,15 @@ dependencies = [ "objc-foundation", ] +[[package]] +name = "mach" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b823e83b2affd8f40a9ee8c29dbc56404c1e34cd2710921f2801e2cf29527afa" +dependencies = [ + "libc", +] + [[package]] name = "malloc_buf" version = "0.0.6" @@ -168,6 +349,41 @@ dependencies = [ "libc", ] +[[package]] +name = "memchr" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400" + +[[package]] +name = "minimp3" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dce0cff6a0bfd3f8b6b2350819bbddd63bc65cc45e53888bdd0ff49dde16d2d5" +dependencies = [ + "minimp3-sys", + "slice-deque", +] + +[[package]] +name = "minimp3-sys" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e21c73734c69dc95696c9ed8926a2b393171d98b3f5f5935686a26a487ab9b90" +dependencies = [ + "cc", +] + +[[package]] +name = "nom" +version = "5.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af" +dependencies = [ + "memchr", + "version_check", +] + [[package]] name = "notify-rust" version = "4.0.0" @@ -227,18 +443,51 @@ dependencies = [ "objc", ] +[[package]] +name = "ogg" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d79f1db9148be9d0e174bb3ac890f6030fcb1ed947267c5a91ee4c91b5a91e15" +dependencies = [ + "byteorder", +] + +[[package]] +name = "peeking_take_while" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" + [[package]] name = "pkg-config" version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d36492546b6af1463394d46f0c834346f31548646f6ba10849802c9c9a27ac33" +[[package]] +name = "proc-macro2" +version = "1.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04f5f085b5d71e2188cb8271e5da0161ad52c3f227a661a3c135fdf28e258b12" +dependencies = [ + "unicode-xid 0.2.1", +] + [[package]] name = "quote" version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" +[[package]] +name = "quote" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37" +dependencies = [ + "proc-macro2", +] + [[package]] name = "redox_syscall" version = "0.1.57" @@ -256,6 +505,35 @@ dependencies = [ "rust-argon2", ] +[[package]] +name = "regex" +version = "1.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c3780fcf44b193bc4d09f36d2a3c87b251da4a046c87795a0d35f4f927ad8e6" +dependencies = [ + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.6.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26412eb97c6b088a6997e05f69403a802a92d520de2f8e63c2b65f9e0f47c4e8" + +[[package]] +name = "rodio" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73bbf260262fd5501b7a17d6827e0d25c1127e921eb177150a060faf6e217a70" +dependencies = [ + "claxon", + "cpal", + "hound", + "lazy_static", + "lewton", + "minimp3", +] + [[package]] name = "rust-argon2" version = "0.8.2" @@ -268,6 +546,35 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "shlex" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2" + +[[package]] +name = "slice-deque" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31ef6ee280cdefba6d2d0b4b78a84a1c1a3f3a4cec98c2d4231c8bc225de0f25" +dependencies = [ + "libc", + "mach", + "winapi", +] + +[[package]] +name = "stdweb" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef5430c8e36b713e13b48a9f709cc21e046723fe44ce34587b73a830203b533e" + [[package]] name = "strum" version = "0.8.0" @@ -280,8 +587,8 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3384590878eb0cab3b128e844412e2d010821e7e091211b9d87324173ada7db8" dependencies = [ - "quote", - "syn", + "quote 0.3.15", + "syn 0.11.11", ] [[package]] @@ -290,9 +597,20 @@ version = "0.11.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" dependencies = [ - "quote", + "quote 0.3.15", "synom", - "unicode-xid", + "unicode-xid 0.0.4", +] + +[[package]] +name = "syn" +version = "1.0.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "891d8d6567fe7c7f8835a3a98af4208f3846fba258c1bc3c31d6e506239f11f9" +dependencies = [ + "proc-macro2", + "quote 1.0.7", + "unicode-xid 0.2.1", ] [[package]] @@ -301,7 +619,27 @@ version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" dependencies = [ - "unicode-xid", + "unicode-xid 0.0.4", +] + +[[package]] +name = "thiserror" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dfdd070ccd8ccb78f4ad66bf1982dc37f620ef696c6b5028fe2ed83dd3d0d08" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd80fc12f73063ac132ac92aceea36734f04a1d93c1240c6944e23a3b8841793" +dependencies = [ + "proc-macro2", + "quote 1.0.7", + "syn 1.0.39", ] [[package]] @@ -315,12 +653,30 @@ dependencies = [ "winapi", ] +[[package]] +name = "tinyvec" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "238ce071d267c5710f9d31451efec16c5ee22de34df17cc05e56cbc92e967117" + [[package]] name = "unicode-xid" version = "0.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" +[[package]] +name = "unicode-xid" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" + +[[package]] +name = "version_check" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed" + [[package]] name = "wasi" version = "0.9.0+wasi-snapshot-preview1" @@ -383,5 +739,5 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1945e12e16b951721d7976520b0832496ef79c31602c7a29d950de79ba74621" dependencies = [ - "bitflags", + "bitflags 0.9.1", ] diff --git a/Cargo.toml b/Cargo.toml index c1c54aa..0825d43 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,3 +8,6 @@ version = "0.1.0" [dependencies] notify-rust = "4.0.0" +rodio = "0.11.0" +directories = "3.0.1" +lazy_static = "1.4.0" diff --git a/src/alert.rs b/src/alert.rs new file mode 100644 index 0000000..67f7d53 --- /dev/null +++ b/src/alert.rs @@ -0,0 +1,29 @@ +use rodio::{Decoder, Source}; +use std::error::Error; +use std::fs::File; +use std::io::BufReader; +use std::path::PathBuf; + +#[derive(Debug, Clone)] +pub struct Alert { + path: PathBuf, +} + +impl Alert { + pub fn new(path: PathBuf) -> Self { + Self { path } + } + + pub fn load(&mut self, path: PathBuf) { + self.path = path; + } + + pub fn play(&self) -> Result<(), Box> { + let file = File::open(&self.path)?; + let device = rodio::default_output_device().ok_or("No default output device found.")?; + let source = Decoder::new(BufReader::new(file))?; + + rodio::play_raw(&device, source.convert_samples()); + Ok(()) + } +} diff --git a/src/lib.rs b/src/lib.rs index 95b4e7e..fc1c9f4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,4 @@ +pub use alert::Alert; pub use pomodoro::Pomodoro; - +mod alert; mod pomodoro; diff --git a/src/main.rs b/src/main.rs index 2867cba..8149248 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,41 @@ +use directories::ProjectDirs; +use domasi::Alert; use domasi::Pomodoro; +use std::fs; +use std::path::PathBuf; fn main() { let mut domasi: Pomodoro = Default::default(); - domasi.start(); + match get_alert() { + Some(alert) => domasi.start_with_alert(alert), + None => domasi.start(), + } +} + +fn get_alert() -> Option { + let alert_dir = ProjectDirs::from("moe", "paoda", "domasi") + .unwrap() + .data_dir() + .to_path_buf() + .join("alert"); + + let file = find_alert_file(alert_dir)?; + Some(Alert::new(file)) +} + +fn find_alert_file(path: PathBuf) -> Option { + let items = fs::read_dir(path).ok()?; + + for entry_result in items { + if let Ok(entry) = entry_result { + if let Some(ext) = entry.path().extension() { + if let Some("mp3") | Some("wav") | Some("ogg") | Some("flac") = ext.to_str() { + return Some(entry.path()); + } + } + } + } + + None } diff --git a/src/pomodoro.rs b/src/pomodoro.rs index 71e5fc2..cc87747 100644 --- a/src/pomodoro.rs +++ b/src/pomodoro.rs @@ -1,3 +1,4 @@ +use super::Alert; use std::error::Error; use std::fmt::{Display, Formatter, Result as FmtResult}; use std::io::{self, Write}; @@ -23,15 +24,30 @@ impl Pomodoro { Self::default() } - pub fn start(&mut self) { + pub fn start_with_alert(&mut self, alert: Alert) { loop { - if let Status::Complete = self.poll() { + if let Status::Complete = self.poll(Some(&alert)) { break; } - thread::sleep(POLLING_RATE); + + Self::sleep(); } } + pub fn start(&mut self) { + loop { + if let Status::Complete = self.poll(None) { + break; + } + + Self::sleep() + } + } + + fn sleep() { + thread::sleep(POLLING_RATE); + } + fn notify_complete(&self) -> Result<(), Box> { let mut toast = notify_rust::Notification::new(); toast.summary("Pomodoro cycle complete!"); @@ -86,7 +102,7 @@ impl Pomodoro { Ok(()) } - fn poll(&mut self) -> Status { + fn poll(&mut self, maybe_alert: Option<&Alert>) -> Status { let status = self.check(); match status { @@ -115,6 +131,10 @@ impl Pomodoro { State::Work | State::ShortBreak | State::LongBreak => Some(Instant::now()), }; + if let Some(alert) = maybe_alert { + let _ = alert.play(); + } + let _ = self.notify(); self.display_time(); }