use rand::Rng; use crate::objects::{AlbumItem, ChunkHeader, DataSet, Database, JumpTable, LetterJumpEntry, ListSortOrder, Playlist, PlaylistIndexEntry, PlaylistItem, TrackItem}; #[derive(Debug, serde::Serialize)] pub struct XDatabase { pub header: Option, pub data: Option, pub children: Vec } #[derive(Debug, serde::Serialize)] pub struct XDataSet { pub header: ChunkHeader, pub data: DataSet, pub child: XSomeList } #[derive(Debug, serde::Serialize, Clone)] pub struct XTrackItem { pub header: ChunkHeader, pub data: TrackItem, pub args: Vec } #[derive(Debug, serde::Serialize)] pub struct XAlbumItem { pub header: ChunkHeader, pub data: AlbumItem, pub args: Vec } #[derive(Debug, serde::Serialize, Clone)] pub struct XPlaylist { pub header: ChunkHeader, pub data: Playlist, pub args: Vec, pub elems: Vec<(PlaylistItem, Vec)> } #[derive(Debug, serde::Serialize, Clone)] pub enum XPlArgument { String(XArgument), IndexEntry(XPlaylistIndexEntry), LetterJumpEntry(XLetterJump), RawArgument(Vec) } #[derive(Debug, serde::Serialize, Clone)] pub struct XPlaylistIndexEntry { pub data: PlaylistIndexEntry, pub v: Vec } #[derive(Debug, serde::Serialize, Clone)] pub struct XLetterJump { pub data: LetterJumpEntry, pub v: Vec } #[derive(Debug, serde::Serialize, Clone)] pub struct XArgument { pub arg_type: u32, pub val: String } #[derive(Debug, serde::Serialize)] pub enum XSomeList { Playlists(Vec), TrackList(Vec), AlbumList(Vec) } impl XPlaylist { pub fn set_title(&mut self, title: String) { self.update_arg(1, title); } pub fn get_title(&self) -> String { self.get_arg(1) } fn get_arg(&self, id: u32) -> String { for arg in self.args.iter() { if let XPlArgument::String(val) = arg { if val.arg_type == id { return val.val.clone(); } } } String::new() } fn update_arg(&mut self, id: u32, val: String) { self.args.retain(|t| { if let XPlArgument::String(s) = t { if s.arg_type == id { return false; } } true }); self.args.push(XPlArgument::String(XArgument { arg_type: id, val })); self.data.string_mhod_count = self.args.len() as u16; self.data.data_object_child_count = self.args.len() as u32; } pub fn new(persistent_playlist_id: u64, sort_order: ListSortOrder) -> Self { Self { header: ChunkHeader::empty(), data: Playlist::new(persistent_playlist_id, sort_order), args: vec![], elems: vec![], } } pub fn add_elem(&mut self, track_id: u32) { let group_id: u32 = rand::random(); self.elems.push((PlaylistItem::new(track_id, group_id), Vec::new())); self.data.playlist_item_count += 1; } } impl XTrackItem { pub fn new(unique_id: u32, size: u32, length: u32, year: u32, bitrate: u32, sample_rate: u32, dbid: u64, sample_count: u64) -> Self { Self { header: ChunkHeader::empty(), data: TrackItem::new(unique_id, size, length, year, bitrate, sample_rate, dbid, sample_count), args: vec![], } } pub fn set_location(&mut self, location: String) { self.update_arg(2, location); } pub fn set_title(&mut self, title: String) { self.update_arg(1, title); } pub fn set_artist(&mut self, artist: String) { self.update_arg(4, artist); } pub fn set_album(&mut self, album: String) { self.update_arg(3, album); } pub fn set_genre(&mut self, genre: String) { self.update_arg(5, genre); } pub fn get_location(&self) -> String { self.get_arg(2) } pub fn get_title(&self) -> String { self.get_arg(1) } pub fn get_artist(&self) -> String { self.get_arg(4) } pub fn get_album(&self) -> String { self.get_arg(3) } pub fn get_genre(&self) -> String { self.get_arg(5) } fn get_arg(&self, id: u32) -> String { self.args.iter().find(|t| t.arg_type == id).map_or(String::new(), |t| t.val.clone()) } pub fn update_arg(&mut self, id: u32, val: String) { self.args.retain(|t| t.arg_type != id); self.args.push(XArgument { arg_type: id, val}); self.data.number_of_strings = self.args.len() as u32; } } impl XDatabase { pub fn find_dataset(&mut self, data_type: u32) -> &mut XDataSet { self.children.iter_mut().find(|d| d.data.data_type == data_type).unwrap() } pub fn remove_track(&mut self, unique_id: u32) { if let XSomeList::TrackList(tracks) = &mut self.find_dataset(1).child { tracks.retain_mut(|t| t.data.unique_id != unique_id); } if let XSomeList::Playlists(playlists) = &mut self.find_dataset(2).child { for playlist in playlists.iter_mut() { playlist.elems.retain_mut(|t| t.0.track_id != unique_id); } } if let XSomeList::Playlists(playlists) = &mut self.find_dataset(3).child { for playlist in playlists.iter_mut() { playlist.elems.retain_mut(|t| t.0.track_id != unique_id); } } } pub fn get_playlists(&mut self) -> Vec { let mut res_pls = Vec::new(); if let XSomeList::Playlists(playlists) = &mut self.find_dataset(2).child { res_pls = playlists.to_vec(); } if let XSomeList::Playlists(playlists) = &mut self.find_dataset(3).child { res_pls = [res_pls, playlists.to_vec()].concat(); } res_pls } pub fn get_unique_id(&mut self) -> u32 { if let XSomeList::TrackList(tracks) = &mut self.find_dataset(1).child { if let Some(n) = tracks.iter().map(|t| t.data.unique_id).max() { return n + 1; } } 1 } pub fn get_track(&mut self, id: u32) -> Option { if let XSomeList::TrackList(tracks) = &mut self.find_dataset(1).child { return tracks.iter().find(|t| t.data.unique_id == id).cloned() } None } pub fn add_track(&mut self, track: XTrackItem) { self.add_track_to_playlists(2, &track); self.add_track_to_playlists(3, &track); if let XSomeList::TrackList(tracks) = &mut self.find_dataset(1).child { tracks.push(track); } } fn add_track_to_playlists(&mut self, n: u32, track: &XTrackItem) { if let XSomeList::Playlists(playlists) = &mut self.find_dataset(n).child { let playlist = playlists.iter_mut().find(|t| t.data.is_master_playlist_flag != 0); if playlist.is_none() { return; } let playlist = playlist.unwrap(); playlist.data.playlist_item_count += 1; let elem = playlist.elems.last().unwrap(); let mut pl_item = elem.0.clone(); pl_item.track_id = track.data.unique_id; pl_item.group_id = rand::thread_rng().gen_range(10..255); let mut args = elem.1.clone(); if let XPlArgument::RawArgument(raw) = args.last_mut().unwrap() { raw[24] = pl_item.group_id as u8; } playlist.elems.push((pl_item, args)); } } }