about summary refs log tree commit diff stats
path: root/src/watch/events/playlist_handler.rs
blob: 09338569eb1b4cbe3c9e993f2d19fd538fd49c80 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
// 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 {
            self.playlist_ids.entry(id).or_insert(hash);
        }

        Ok(&self.playlist_ids)
    }
}