mod client; mod popup; use self::popup::Popup; use crate::modules::mpd::client::{get_connection, get_duration, get_elapsed}; use crate::modules::mpd::popup::{MpdPopup, PopupEvent}; use crate::modules::{Module, ModuleInfo}; use color_eyre::Result; use dirs::{audio_dir, home_dir}; use glib::Continue; use gtk::prelude::*; use gtk::{Button, Orientation}; use mpd_client::commands::responses::{PlayState, Song, Status}; use mpd_client::{commands, Tag}; use regex::Regex; use serde::Deserialize; use std::path::PathBuf; use std::time::Duration; use tokio::spawn; use tokio::sync::mpsc; use tokio::time::sleep; use tracing::error; #[derive(Debug, Deserialize, Clone)] pub struct MpdModule { #[serde(default = "default_socket")] host: String, #[serde(default = "default_format")] format: String, #[serde(default = "default_icon_play")] icon_play: Option, #[serde(default = "default_icon_pause")] icon_pause: Option, #[serde(default = "default_music_dir")] music_dir: PathBuf, } fn default_socket() -> String { String::from("localhost:6600") } fn default_format() -> String { String::from("{icon} {title} / {artist}") } #[allow(clippy::unnecessary_wraps)] fn default_icon_play() -> Option { Some(String::from("")) } #[allow(clippy::unnecessary_wraps)] fn default_icon_pause() -> Option { Some(String::from("")) } fn default_music_dir() -> PathBuf { audio_dir().unwrap_or_else(|| home_dir().map(|dir| dir.join("Music")).unwrap_or_default()) } /// Attempts to read the first value for a tag /// (since the MPD client returns a vector of tags, or None) pub fn try_get_first_tag(vec: Option<&Vec>) -> Option<&str> { match vec { Some(vec) => vec.first().map(String::as_str), None => None, } } /// Formats a duration given in seconds /// in hh:mm format fn format_time(time: u64) -> String { let minutes = (time / 60) % 60; let seconds = time % 60; format!("{:0>2}:{:0>2}", minutes, seconds) } /// Extracts the formatting tokens from a formatting string fn get_tokens(re: &Regex, format_string: &str) -> Vec { re.captures_iter(format_string) .map(|caps| caps[1].to_string()) .collect::>() } enum Event { Open, Update(Box>), } impl Module