diff --git a/Cargo.lock b/Cargo.lock index b22b303..a889570 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -47,6 +47,28 @@ dependencies = [ "version_check", ] +[[package]] +name = "alsa" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5915f52fe2cf65e83924d037b6c5290b7cee097c6b5c8700746e6168a343fd6b" +dependencies = [ + "alsa-sys", + "bitflags", + "libc", + "nix 0.23.1", +] + +[[package]] +name = "alsa-sys" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db8fee663d06c4e303404ef5f40488a53e062f89ba8bfed81f42325aafad1527" +dependencies = [ + "libc", + "pkg-config", +] + [[package]] name = "android_system_properties" version = "0.1.5" @@ -123,6 +145,25 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "bindgen" +version = "0.59.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bd2a9a458e8f4304c52c43ebb0cfbd520289f8379a52e329a38afda99bf8eb8" +dependencies = [ + "bitflags", + "cexpr", + "clang-sys", + "lazy_static", + "lazycell", + "peeking_take_while", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", +] + [[package]] name = "bit-set" version = "0.5.3" @@ -206,6 +247,9 @@ name = "cc" version = "1.0.73" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" +dependencies = [ + "jobserver", +] [[package]] name = "cesu8" @@ -213,6 +257,15 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", +] + [[package]] name = "cfg-if" version = "1.0.0" @@ -235,10 +288,21 @@ dependencies = [ ] [[package]] -name = "clap" -version = "4.0.14" +name = "clang-sys" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ea54a38e4bce14ff6931c72e5b3c43da7051df056913d4e7e1fcdb1c03df69d" +checksum = "fa2e27ae6ab525c3d369ded447057bca5438d86dc3a68f6faafb8269ba82ebf3" +dependencies = [ + "glob", + "libc", + "libloading", +] + +[[package]] +name = "clap" +version = "4.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bf8832993da70a4c6d13c581f4463c2bdda27b9bf1c5498dc4365543abe6d6f" dependencies = [ "atty", "bitflags", @@ -273,6 +337,12 @@ dependencies = [ "os_str_bytes", ] +[[package]] +name = "claxon" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bfbf56724aa9eca8afa4fcfadeb479e722935bb2a0900c2d37e0cc477af0688" + [[package]] name = "clipboard-win" version = "4.4.2" @@ -403,6 +473,50 @@ dependencies = [ "libc", ] +[[package]] +name = "coreaudio-rs" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11894b20ebfe1ff903cbdc52259693389eea03b94918a2def2c30c3bf227ad88" +dependencies = [ + "bitflags", + "coreaudio-sys", +] + +[[package]] +name = "coreaudio-sys" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3dff444d80630d7073077d38d40b4501fd518bd2b922c2a55edcc8b0f7be57e6" +dependencies = [ + "bindgen", +] + +[[package]] +name = "cpal" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d466b47cf0ea4100186a7c12d7d0166813dda7cf648553554c9c39c6324841b" +dependencies = [ + "alsa", + "core-foundation-sys", + "coreaudio-rs", + "jni", + "js-sys", + "libc", + "mach", + "ndk 0.7.0", + "ndk-context", + "nix 0.23.1", + "oboe", + "once_cell", + "parking_lot", + "stdweb", + "thiserror", + "web-sys", + "windows", +] + [[package]] name = "crc32fast" version = "1.3.2" @@ -794,6 +908,12 @@ dependencies = [ "xml-rs", ] +[[package]] +name = "glob" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" + [[package]] name = "glow" version = "0.11.2" @@ -940,6 +1060,12 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df" +[[package]] +name = "hound" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d13cdbd5dbb29f9c88095bbdc2590c9cba0d0a1269b983fef6b2cdd7e9f4db1" + [[package]] name = "ident_case" version = "1.0.1" @@ -1004,6 +1130,15 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" +[[package]] +name = "jobserver" +version = "0.1.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "068b1ee6743e4d11fb9c6a1e6064b3693a1b600e7f5f5988047d98b3dc9fb90b" +dependencies = [ + "libc", +] + [[package]] name = "js-sys" version = "0.3.60" @@ -1015,13 +1150,14 @@ dependencies = [ [[package]] name = "katabastird" -version = "0.1.0" +version = "1.0.0" dependencies = [ "clap", "eframe", "egui", "egui_extras", "naga 0.10.0", + "rodio", "wgpu 0.14.0", ] @@ -1048,6 +1184,23 @@ 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.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "777b48df9aaab155475a83a7df3070395ea1ac6902f5cd062b8f2b028075c030" +dependencies = [ + "byteorder", + "ogg", + "tinyvec", +] + [[package]] name = "libc" version = "0.2.135" @@ -1083,6 +1236,15 @@ dependencies = [ "cfg-if", ] +[[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" @@ -1136,6 +1298,26 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" +[[package]] +name = "minimp3" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "985438f75febf74c392071a975a29641b420dd84431135a6e6db721de4b74372" +dependencies = [ + "minimp3-sys", + "slice-deque", + "thiserror", +] + +[[package]] +name = "minimp3-sys" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e21c73734c69dc95696c9ed8926a2b393171d98b3f5f5935686a26a487ab9b90" +dependencies = [ + "cc", +] + [[package]] name = "miniz_oxide" version = "0.5.4" @@ -1306,6 +1488,19 @@ dependencies = [ "memoffset", ] +[[package]] +name = "nix" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f866317acbd3a240710c63f065ffb1e4fd466259045ccb504130b7f668f35c6" +dependencies = [ + "bitflags", + "cc", + "cfg-if", + "libc", + "memoffset", +] + [[package]] name = "nix" version = "0.24.2" @@ -1334,6 +1529,17 @@ dependencies = [ "minimal-lexical", ] +[[package]] +name = "num-derive" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "num-traits" version = "0.2.15" @@ -1403,6 +1609,38 @@ dependencies = [ "objc", ] +[[package]] +name = "oboe" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27f63c358b4fa0fbcfefd7c8be5cfc39c08ce2389f5325687e7762a48d30a5c1" +dependencies = [ + "jni", + "ndk 0.6.0", + "ndk-context", + "num-derive", + "num-traits", + "oboe-sys", +] + +[[package]] +name = "oboe-sys" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3370abb7372ed744232c12954d920d1a40f1c4686de9e79e800021ef492294bd" +dependencies = [ + "cc", +] + +[[package]] +name = "ogg" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6951b4e8bf21c8193da321bcce9c9dd2e13c858fe078bf9054a288b419ae5d6e" +dependencies = [ + "byteorder", +] + [[package]] name = "once_cell" version = "1.15.0" @@ -1456,6 +1694,12 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "peeking_take_while" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" + [[package]] name = "percent-encoding" version = "2.2.0" @@ -1594,12 +1838,40 @@ dependencies = [ "bitflags", ] +[[package]] +name = "regex" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b" +dependencies = [ + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.6.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244" + [[package]] name = "renderdoc-sys" version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1382d1f0a252c4bf97dc20d979a2fdd05b024acd7c2ed0f7595d7817666a157" +[[package]] +name = "rodio" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb10b653d5ec0e9411a2e7d46e2c7f4046fd87d35b9955bd73ba4108d69072b5" +dependencies = [ + "claxon", + "cpal", + "hound", + "lewton", + "minimp3", +] + [[package]] name = "rustc-hash" version = "1.1.0" @@ -1696,6 +1968,23 @@ dependencies = [ "libc", ] +[[package]] +name = "shlex" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3" + +[[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 = "slotmap" version = "1.0.6" @@ -1756,6 +2045,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +[[package]] +name = "stdweb" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef5430c8e36b713e13b48a9f709cc21e046723fe44ce34587b73a830203b533e" + [[package]] name = "str-buf" version = "1.0.6" @@ -2381,17 +2676,30 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows" +version = "0.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57b543186b344cc61c85b5aab0d2e3adf4e0f99bc076eff9aa5927bcc0b8a647" +dependencies = [ + "windows_aarch64_msvc 0.37.0", + "windows_i686_gnu 0.37.0", + "windows_i686_msvc 0.37.0", + "windows_x86_64_gnu 0.37.0", + "windows_x86_64_msvc 0.37.0", +] + [[package]] name = "windows-sys" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" dependencies = [ - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_msvc", + "windows_aarch64_msvc 0.36.1", + "windows_i686_gnu 0.36.1", + "windows_i686_msvc 0.36.1", + "windows_x86_64_gnu 0.36.1", + "windows_x86_64_msvc 0.36.1", ] [[package]] @@ -2400,30 +2708,60 @@ version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" +[[package]] +name = "windows_aarch64_msvc" +version = "0.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2623277cb2d1c216ba3b578c0f3cf9cdebeddb6e66b1b218bb33596ea7769c3a" + [[package]] name = "windows_i686_gnu" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" +[[package]] +name = "windows_i686_gnu" +version = "0.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3925fd0b0b804730d44d4b6278c50f9699703ec49bcd628020f46f4ba07d9e1" + [[package]] name = "windows_i686_msvc" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" +[[package]] +name = "windows_i686_msvc" +version = "0.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce907ac74fe331b524c1298683efbf598bb031bc84d5e274db2083696d07c57c" + [[package]] name = "windows_x86_64_gnu" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" +[[package]] +name = "windows_x86_64_gnu" +version = "0.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2babfba0828f2e6b32457d5341427dcbb577ceef556273229959ac23a10af33d" + [[package]] name = "windows_x86_64_msvc" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" +[[package]] +name = "windows_x86_64_msvc" +version = "0.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4dd6dc7df2d84cf7b33822ed5b86318fb1781948e9663bacd047fc9dd52259d" + [[package]] name = "winit" version = "0.27.4" diff --git a/Cargo.toml b/Cargo.toml index 965f61c..2c357f4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,15 +1,16 @@ [package] name = "katabastird" -version = "0.1.0" +version = "1.0.0" edition = "2021" rust-version = "1.61" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -clap = { version = "4.0.14", features = ["derive", "env", "unicode", "suggestions", "usage"] } -eframe = { version = "0.19.0", features = ["wgpu"] } -egui = { version = "0.19.0", features = ["bytemuck"] } -egui_extras = "0.19.0" -naga = { version = "0.10.0", features = ["spv-out", "wgsl-out", "wgsl-in"] } -wgpu = { version = "0.14.0", features = ["naga", "spirv"] } +clap = { version = "4", features = ["derive", "env", "unicode", "suggestions", "usage"] } +eframe = { version = "0.19", features = ["wgpu"] } +egui = { version = "0.19", features = ["bytemuck"] } +egui_extras = "0.19" +naga = { version = "0.10", features = ["spv-out", "wgsl-out", "wgsl-in"] } +rodio = "0.16" +wgpu = { version = "0.14", features = ["naga", "spirv"] } diff --git a/Predator.ttf b/Predator.ttf new file mode 100644 index 0000000..2aa8304 Binary files /dev/null and b/Predator.ttf differ diff --git a/src/main.rs b/src/main.rs index 9172ff3..fd19e8d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -46,7 +46,7 @@ fn main() { let cli = Cli::parse(); let seconds = cli.hours * 3600 + cli.minutes * 60 + cli.seconds; - let duration = Duration::from_secs(seconds.max(30)); + let duration = Duration::from_secs(seconds); let direction = if cli.count_up { CountDirection::Up @@ -57,6 +57,15 @@ fn main() { eframe::run_native( "katabastird", options, - Box::new(move |_cc| Box::new(Timer::new(duration, direction, !cli.running))), + Box::new(move |cc| { + Box::new(Timer::new( + duration, + direction, + cc, + !cli.running, + cli.predator, + cli.alarm, + )) + }), ); } diff --git a/src/timer.rs b/src/timer.rs index 804eba7..4bf263c 100644 --- a/src/timer.rs +++ b/src/timer.rs @@ -2,7 +2,7 @@ use egui::{Color32, Direction, FontId, Layout, RichText, Ui}; use egui_extras::{Size, StripBuilder}; use std::time::{Duration, Instant}; -use eframe::App; +use eframe::{App, CreationContext}; #[derive(Debug, Clone, Copy)] pub enum CountDirection { @@ -10,11 +10,13 @@ pub enum CountDirection { Down, } -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone)] pub struct Timer { direction: CountDirection, duration: Duration, state: State, + tstart: Instant, + alarm: Option, } #[derive(Debug, Clone, Copy)] @@ -50,6 +52,8 @@ impl Default for Timer { direction: CountDirection::Down, duration: dur, state: State::Unstarted, + tstart: Instant::now(), + alarm: None, } } } @@ -74,12 +78,36 @@ impl App for Timer { } impl Timer { - pub fn new(duration: Duration, direction: CountDirection, paused: bool) -> Self { + pub fn new( + duration: Duration, + direction: CountDirection, + ctx: &CreationContext, + paused: bool, + predator: bool, + alarm: Option, + ) -> Self { + let tstart = Instant::now(); + if predator { + let mut fonts = egui::FontDefinitions::default(); + fonts.font_data.insert( + "predator".to_owned(), + egui::FontData::from_static(include_bytes!("../Predator.ttf")), + ); + fonts + .families + .entry(egui::FontFamily::Monospace) + .or_default() + .insert(0, "predator".to_owned()); + ctx.egui_ctx.set_fonts(fonts); + } + ctx.egui_ctx.request_repaint_after(Duration::from_secs(1)); if paused { Timer { duration, direction, state: State::Unstarted, + tstart, + alarm, } } else { let cs = ChronoState { @@ -90,6 +118,8 @@ impl Timer { duration, direction, state: State::Running(cs), + tstart, + alarm, } } } @@ -182,21 +212,36 @@ impl Timer { }); } + // if we're counting up, do the right thing let remaining = match self.direction { CountDirection::Down => remaining, - _ => self.duration - remaining, + CountDirection::Up => self.duration - remaining, }; // now the numbers + let color = if is_paused { + let blink = (Instant::now() - self.tstart).as_secs() % 2 == 0; + if blink { + Color32::BLACK + } else { + Color32::DARK_GRAY + } + } else { + Color32::DARK_GRAY + }; let hours = remaining.as_secs() / 3600; let minutes = (remaining.as_secs() / 60) % 60; let seconds = remaining.as_secs() % 60; let tsize = size * 0.7; - let hours = RichText::new(format!("{:02}", hours)).font(FontId::monospace(tsize)); - let minutes = - RichText::new(format!("{:02}", minutes)).font(FontId::monospace(tsize)); - let seconds = - RichText::new(format!("{:02}", seconds)).font(FontId::monospace(tsize)); + let hours = RichText::new(format!("{:02}", hours)) + .font(FontId::monospace(tsize)) + .color(color); + let minutes = RichText::new(format!("{:02}", minutes)) + .font(FontId::monospace(tsize)) + .color(color); + let seconds = RichText::new(format!("{:02}", seconds)) + .font(FontId::monospace(tsize)) + .color(color); strip.strip(|strip| { strip .sizes(Size::relative(0.33), 3) @@ -215,6 +260,15 @@ impl Timer { }); }); + if remaining.is_zero() { + if let Some(alarm_file) = &self.alarm { + let alarm_file = alarm_file.to_owned(); + std::thread::spawn(move || alarm(alarm_file)); + } + self.state = State::Unstarted; + return; + } + let cs = ChronoState { remaining, started }; if is_paused { if self.state == State::Unstarted { @@ -226,3 +280,21 @@ impl Timer { } } } + +fn alarm(path: String) { + use rodio::{source::Source, Decoder, OutputStream}; + use std::fs::File; + use std::io::BufReader; + + let (_stream, stream_handle) = OutputStream::try_default().unwrap(); + let file = BufReader::new(File::open(path).unwrap()); + let source = Decoder::new(file).unwrap(); + let dur = if let Some(dur) = source.total_duration() { + dur + } else { + Duration::from_secs(10) + }; + + let _ = stream_handle.play_raw(source.convert_samples()); + std::thread::sleep(dur); +}