Add audio playback upon notification
This commit is contained in:
29
src/alert.rs
Normal file
29
src/alert.rs
Normal file
@@ -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<dyn Error>> {
|
||||
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(())
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
pub use alert::Alert;
|
||||
pub use pomodoro::Pomodoro;
|
||||
|
||||
mod alert;
|
||||
mod pomodoro;
|
||||
|
||||
36
src/main.rs
36
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<Alert> {
|
||||
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<PathBuf> {
|
||||
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
|
||||
}
|
||||
|
||||
@@ -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<dyn Error>> {
|
||||
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();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user