diff --git a/Cargo.toml b/Cargo.toml index cac8b7d..f616812 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,7 +15,7 @@ categories = ["date-and-time"] [features] default = ["desktop", "sound"] desktop = ["dep:notify-rust"] -sound = ["dep:rodio", "desktop"] +sound = ["dep:rodio"] [dependencies] @@ -25,5 +25,7 @@ humantime = "2.1.0" libpt = { version = "0.6.0", features = ["cli"] } notify-rust = { version = "4.11.0", optional = true } ratatui = "0.27.0" -rodio = { version = "0.19.0", optional = true } +rodio = { version = "0.19.0", optional = true, default-features = false, features = [ + "mp3", +] } tui-big-text = "0.4.5" diff --git a/README.md b/README.md index 9bc9bf1..6f6c313 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,6 @@ and sound alerts for countdown mode. (Use `cargo build -r --no-default-features` ## Acknoledgements -The included alarm sound is from pixabay, royalty free: +The included alarm sound is from [freesound.org](https://freesound.org): --> ["Alarm Clock 1"](https://pixabay.com/?utm_source=link-attribution&utm_medium=referral&utm_campaign=music&utm_content=105903) +-> ["effect_notify.wav" by ricemaster (CC-0)](https://freesound.org/people/ricemaster/sounds/278142/) diff --git a/data/media/278142__ricemaster__effect_notify.wav b/data/media/278142__ricemaster__effect_notify.wav new file mode 100755 index 0000000..a396dcd Binary files /dev/null and b/data/media/278142__ricemaster__effect_notify.wav differ diff --git a/data/media/alarm.mp3 b/data/media/alarm.mp3 index 26d6c33..eeabdfc 100755 Binary files a/data/media/alarm.mp3 and b/data/media/alarm.mp3 differ diff --git a/src/clock.rs b/src/clock.rs index 194c30b..a3c59bc 100644 --- a/src/clock.rs +++ b/src/clock.rs @@ -77,6 +77,9 @@ pub struct Clock { /// Precision: only to seconds #[clap(short = 'u', long, value_parser = humantime::parse_duration)] pub countdown: Option, + /// Play a notification sound when the countdown is up + #[clap(short, long)] + pub sound: bool, // internal variables #[clap(skip)] @@ -406,19 +409,26 @@ impl Clock { fn notify(&mut self) -> anyhow::Result<()> { Self::beep()?; #[cfg(feature = "sound")] - { - trace!("playing bundled sound"); - use rodio::{source::Source, Decoder, OutputStream}; + if self.sound { + std::thread::spawn(|| { + use rodio::{Decoder, OutputStream, Sink}; + // only 30 KiB, so let's just include it in the binary and not worry about reading it + // from the fs and somehow making the file be there + const SOUND_RAW: &[u8] = include_bytes!("../data/media/alarm.mp3"); - // only 30 KiB, so let's just include it in the binary and not worry about reading it - // from the fs and somehow making the file be there - let sound: Cursor<_> = std::io::Cursor::new(include_bytes!("../data/media/alarm.mp3")); + trace!("playing bundled sound"); - // Get an output stream handle to the default physical sound device - let (_stream, stream_handle) = OutputStream::try_default().unwrap(); - let source = Decoder::new(sound).expect("could not load the included sound"); - stream_handle.play_raw(source.convert_samples())?; // the sound plays in another thread - debug!("played bundled sound"); + let sound_data: Cursor<_> = std::io::Cursor::new(SOUND_RAW); + + let (_stream, stream_handle) = OutputStream::try_default().unwrap(); + let sink = Sink::try_new(&stream_handle).unwrap(); + sink.append( + Decoder::new(sound_data).expect("could not decode the bundled alarm sound"), + ); + sink.sleep_until_end(); + + debug!("played bundled sound"); + }); } #[cfg(feature = "desktop")] {