mod config; use crate::clients::music::{ self, MusicClient, PlayerState, PlayerUpdate, ProgressTick, Status, Track, }; use crate::gtk_helpers::add_class; use crate::image::{new_icon_button, new_icon_label, ImageProvider}; use crate::modules::{Module, ModuleInfo, ModuleUpdateEvent, ModuleWidget, WidgetContext}; use crate::popup::Popup; use crate::{send_async, try_send}; use color_eyre::Result; use glib::{Continue, PropertySet}; use gtk::prelude::*; use gtk::{Button, IconTheme, Label, Orientation, Scale}; use regex::Regex; use std::path::PathBuf; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; use std::time::Duration; use tokio::spawn; use tokio::sync::mpsc::{Receiver, Sender}; use tracing::error; pub use self::config::MusicModule; use self::config::PlayerType; #[derive(Debug)] pub enum PlayerCommand { Previous, Play, Pause, Next, Volume(u8), Seek(Duration), } /// Formats a duration given in seconds /// in hh:mm format fn format_time(duration: Duration) -> String { let time = duration.as_secs(); let minutes = (time / 60) % 60; let seconds = time % 60; format!("{minutes:0>2}:{seconds:0>2}") } /// 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::>() } #[derive(Clone, Debug)] pub enum ControllerEvent { Update(Option), UpdateProgress(ProgressTick), } #[derive(Clone, Debug)] pub struct SongUpdate { song: Track, status: Status, display_string: String, } async fn get_client( player_type: PlayerType, host: &str, music_dir: PathBuf, ) -> Box> { match player_type { PlayerType::Mpd => music::get_client(music::ClientType::Mpd { host, music_dir }), PlayerType::Mpris => music::get_client(music::ClientType::Mpris {}), } .await } impl Module