use std::fmt;
use std::thread;
use iced::widget::Text;
use rodio::{Decoder, DeviceSinkBuilder, Player};
use serde::{Deserialize, Serialize};
use crate::gui::styles::style_constants::FONT_SIZE_FOOTER;
use crate::notifications::types::sound::Sound::{Gulp, Pop, Swhoosh};
use crate::utils::error_logger::{ErrorLogger, Location};
use crate::utils::types::icon::Icon;
use crate::{StyleType, location};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
pub enum Sound {
Gulp,
#[default]
Pop,
Swhoosh,
None,
}
pub const GULP: &[u8] = include_bytes!("../../../resources/sounds/gulp.mp3");
pub const POP: &[u8] = include_bytes!("../../../resources/sounds/pop.mp3");
pub const SWHOOSH: &[u8] = include_bytes!("../../../resources/sounds/swhoosh.mp3");
impl fmt::Display for Sound {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{self:?}")
}
}
impl Sound {
pub(crate) const ALL: [Sound; 4] = [Gulp, Pop, Swhoosh, Sound::None];
fn mp3_sound(self) -> &'static [u8] {
match self {
Gulp => GULP,
Pop => POP,
Swhoosh => SWHOOSH,
Sound::None => &[],
}
}
pub fn get_text<'a>(self) -> iced::widget::Text<'a, StyleType> {
match self {
Sound::Gulp => Text::new("Gulp"),
Sound::Pop => Text::new("Pop"),
Sound::Swhoosh => Text::new("Swhoosh"),
Sound::None => Icon::Forbidden.to_text(),
}
.size(FONT_SIZE_FOOTER)
}
}
pub fn play(sound: Sound, volume: u8) {
if sound.eq(&Sound::None) || volume == 0 || cfg!(test) {
return;
}
let mp3_sound = sound.mp3_sound();
let _ = thread::Builder::new()
.name("thread_play_sound".to_string())
.spawn(move || {
let Ok(mut stream_handle) = DeviceSinkBuilder::open_default_sink().log_err(location!())
else {
return;
};
stream_handle.log_on_drop(false);
let player = Player::connect_new(stream_handle.mixer());
let data = std::io::Cursor::new(mp3_sound);
let Ok(source) = Decoder::new(data).log_err(location!()) else {
return;
};
player.set_volume(f32::from(volume) / 200.0); player.append(source);
player.sleep_until_end();
})
.log_err(location!());
}