diff options
Diffstat (limited to 'src/watch/events/playlist_handler.rs')
-rw-r--r-- | src/watch/events/playlist_handler.rs | 96 |
1 files changed, 96 insertions, 0 deletions
diff --git a/src/watch/events/playlist_handler.rs b/src/watch/events/playlist_handler.rs new file mode 100644 index 0000000..8f2f322 --- /dev/null +++ b/src/watch/events/playlist_handler.rs @@ -0,0 +1,96 @@ +// yt - A fully featured command line YouTube client +// +// Copyright (C) 2024 Benedikt Peetz <benedikt.peetz@b-peetz.de> +// 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 <https://www.gnu.org/licenses/gpl-3.0.txt>. + +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<String, ExtractorHash>, + + /// A map of the playlist_entry_id field to their corresponding extractor hashes. + playlist_ids: HashMap<PlaylistEntryId, ExtractorHash>, +} +impl PlaylistHandler { + pub fn from_cache(cache: HashMap<String, ExtractorHash>) -> 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<PlaylistEntryId, ExtractorHash>> { + 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<String>, + id: Option<PlaylistEntryId>, + } + 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<PlaylistEntryId, ExtractorHash> = + 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 { + if !self.playlist_ids.contains_key(&id) { + self.playlist_ids.insert(id, hash); + } + } + + Ok(&self.playlist_ids) + } +} |