// yt - A fully featured command line YouTube client // // Copyright (C) 2024 Benedikt Peetz // SPDX-License-Identifier: GPL-3.0-or-later // // This file is part of Yt. // // You should have received a copy of the License along with this program. // If not, see . use std::collections::HashMap; use anyhow::Result; use libmpv2::{events::PlaylistEntryId, mpv_node::MpvNode, Mpv}; use crate::storage::video_database::extractor_hash::ExtractorHash; #[derive(Debug, Default)] pub struct PlaylistHandler { /// A map of the original file paths to the videos extractor hashes. /// Used to get the extractor hash from a video returned by mpv playlist_cache: HashMap, /// A map of the playlist_entry_id field to their corresponding extractor hashes. playlist_ids: HashMap, } impl PlaylistHandler { pub fn from_cache(cache: HashMap) -> Self { Self { playlist_cache: cache, playlist_ids: HashMap::new(), } } pub fn reserve(&mut self, len: usize) { self.playlist_cache.reserve(len) } pub fn add(&mut self, cache_path: String, extractor_hash: ExtractorHash) { assert_eq!( self.playlist_cache.insert(cache_path, extractor_hash), None, "Only new video should ever be added" ); } pub fn playlist_ids(&mut self, mpv: &Mpv) -> Result<&HashMap> { let mpv_playlist: Vec<(String, PlaylistEntryId)> = match mpv.get_property("playlist")? { MpvNode::ArrayIter(array) => array .map(|val| match val { MpvNode::MapIter(map) => { struct BuildPlaylistEntry { filename: Option, id: Option, } let mut entry = BuildPlaylistEntry { filename: None, id: None, }; map.for_each(|(key, value)| match key.as_str() { "filename" => { entry.filename = Some(value.str().expect("work").to_owned()) } "id" => { entry.id = Some(PlaylistEntryId::new(value.i64().expect("Works"))) } _ => (), }); (entry.filename.expect("is some"), entry.id.expect("is some")) } _ => unreachable!(), }) .collect(), _ => unreachable!(), }; let mut playlist: HashMap = HashMap::with_capacity(mpv_playlist.len()); for (path, key) in mpv_playlist { let hash = self .playlist_cache .get(&path) .expect("All path should also be stored in the cache") .to_owned(); playlist.insert(key, hash); } for (id, hash) in playlist { self.playlist_ids.entry(id).or_insert(hash); } Ok(&self.playlist_ids) } }