use std::{ops::Deref, path::PathBuf}; #[derive(Debug, Default, Clone, Eq, PartialEq, Hash)] pub struct ListState { offset: usize, selected: Option, } impl ListState { pub fn offset(&self) -> usize { self.offset } pub fn offset_mut(&mut self) -> &mut usize { &mut self.offset } pub fn with_selected(mut self, selected: Option) -> Self { self.selected = selected; self } pub fn with_offset(mut self, offset: usize) -> Self { self.offset = offset; self } pub fn selected(&self) -> Option { self.selected } pub fn select(&mut self, index: Option) { self.selected = index; if index.is_none() { self.offset = 0; } } } #[derive(Debug, Default)] pub struct StatefulList { pub state: ListState, pub items: Vec, } impl StatefulList where T: Deref + Eq, { pub fn with_items(items: Vec) -> StatefulList { StatefulList { state: ListState::default(), items, } } pub fn next(&mut self) { let i = match self.state.selected() { Some(i) => { if i >= self.items.len() - 1 { 0 } else { i + 1 } } None => 0, }; self.state.select(Some(i)); } pub fn previous(&mut self) { let i = match self.state.selected() { Some(i) => { if i == 0 { self.items.len() - 1 } else { i - 1 } } None => 0, }; self.state.select(Some(i)); } pub fn index_of(&self, item: T) -> Option { self.items.iter().position(|element| *element == item) } pub fn current(&self) -> Option<&T> { self.state .selected .map_or(None, |index| self.items.get(index)) } pub fn current_mut(&mut self) -> Option<&mut T> { self.state .selected .map_or(None, |index| self.items.get_mut(index)) } } pub type PlaylistElement = PathBuf; pub enum PlaylistType { Directory, Queue, } #[derive(Debug)] pub struct DirectoryPlaylist { pub directory: PathBuf, pub playlist: StatefulList, } #[derive(Debug, Default)] pub struct QueuePlaylist { pub playlist: StatefulList, } impl QueuePlaylist { pub fn generate_mock() -> Self { Self { playlist: StatefulList::with_items(vec![ "/home/hheikkinen/Music/Mariya Takeuchi/Mariya Takeuchi (竹内 まりや) - September [Lyrics Kan⧸Rom⧸Eng] [3wkxIBBP7Vg].opus", "/home/hheikkinen/Music/Compilerbau - Le Jardin/LEJARDIN.OGG", "/home/hheikkinen/Music/Casiopea - Mint Jams (1982) FULL ALBUM/001 Take Me.opus", "/home/hheikkinen/Music/Casiopea - Mint Jams (1982) FULL ALBUM/002 Asayake.opus", "/home/hheikkinen/Music/A Groovy Thing/01 - Flamingosis - A Groovy Intro.mp3", "/home/hheikkinen/Music/Brian Ellis - Smocaine 3/Brian Ellis - Smocaine 3- An MDE Film OST - 01 Smocaine Theme (TV Edit).wav", "/home/hheikkinen/Music/Jun Fukamachi - Starview HCT-5808/T-02.m4a", "/home/hheikkinen/Music/noby/Fluidy [189046035].flac", ].iter().map(|val| val.into()).collect()), } } } #[derive(Debug)] pub struct TrackChangeOptions { pub shuffle: bool, pub next: bool, pub repeat: bool, } impl Default for TrackChangeOptions { fn default() -> Self { Self { shuffle: false, next: true, repeat: true, } } } pub mod server { use std::{fmt::Debug, path::PathBuf}; #[derive(Debug)] pub enum ServerError { Other(String), Io(std::io::Error), AlreadyRunning, NotRunning, MissingRuntimeDir(PathBuf), } impl ServerError { pub fn from_debuggable(err: impl Debug) -> Self { Self::Other(format!("Unexpected error: {err:?}").to_string()) } } }