about summary refs log tree commit diff stats
path: root/src/watch/mod.rs
blob: 376b2455b14c618d507cb048172d0a813aac3443 (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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
// 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 events::MpvEventHandler;
use libmpv2::{events::EventContext, Mpv};
use log::{debug, info, warn};

use crate::{
    app::App,
    cache::maintain,
    storage::video_database::{extractor_hash::ExtractorHash, getters::get_videos, VideoStatus},
};

pub mod events;

pub async fn watch(app: &App) -> Result<()> {
    maintain(app, false).await?;

    // set some default values, to make things easier (these can be overridden by the config file,
    // which we load later)
    let mpv = Mpv::with_initializer(|mpv| {
        // Enable default key bindings, so the user can actually interact with
        // the player (and e.g. close the window).
        mpv.set_property("input-default-bindings", "yes")?;
        mpv.set_property("input-vo-keyboard", "yes")?;

        // Show the on screen controller.
        mpv.set_property("osc", "yes")?;

        // Don't automatically advance to the next video (or exit the player)
        mpv.set_option("keep-open", "always")?;
        Ok(())
    })?;

    let config_path = &app.config.paths.mpv_config_path;
    if config_path.try_exists()? {
        info!("Found mpv.conf at '{}'!", config_path.display());
        mpv.execute(
            "load-config-file",
            &[config_path.to_str().expect("This should be utf8-able")],
        )?;
    } else {
        warn!(
            "Did not find a mpv.conf file at '{}'",
            config_path.display()
        );
    }

    let input_path = &app.config.paths.mpv_input_path;
    if input_path.try_exists()? {
        info!("Found mpv.input.conf at '{}'!", input_path.display());
        mpv.execute(
            "load-input-conf",
            &[input_path.to_str().expect("This should be utf8-able")],
        )?;
    } else {
        warn!(
            "Did not find a mpv.input.conf file at '{}'",
            input_path.display()
        );
    }

    let mut ev_ctx = EventContext::new(mpv.ctx);
    ev_ctx.disable_deprecated_events()?;

    let play_things = get_videos(app, &[VideoStatus::Cached], Some(false)).await?;
    info!(
        "{} videos are cached and ready to be played",
        play_things.len()
    );

    let mut playlist_cache: HashMap<String, ExtractorHash> =
        HashMap::with_capacity(play_things.len());

    for play_thing in play_things {
        debug!("Adding '{}' to playlist.", play_thing.title);

        let orig_cache_path = play_thing.cache_path.expect("Is cached and thus some");
        let cache_path = orig_cache_path.to_str().expect("Should be vaild utf8");
        let fmt_cache_path = format!("\"{}\"", cache_path);

        let args = &[&fmt_cache_path, "append-play"];

        mpv.execute("loadfile", args)?;

        playlist_cache.insert(cache_path.to_owned(), play_thing.extractor_hash);
    }

    let mut mpv_event_handler = MpvEventHandler::from_playlist(playlist_cache);
    loop {
        while mpv_event_handler.check_idle(&app, &mpv).await? {}

        if let Some(ev) = ev_ctx.wait_event(600.) {
            match ev {
                Ok(event) => {
                    debug!("Mpv event triggered: {:#?}", event);
                    if mpv_event_handler.handle_mpv_event(app, &mpv, event).await? {
                        break;
                    }
                }
                Err(e) => debug!("Mpv Event errored: {}", e),
            }
        }
    }

    Ok(())
}