about summary refs log tree commit diff stats
path: root/src/watch/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/watch/mod.rs118
1 files changed, 118 insertions, 0 deletions
diff --git a/src/watch/mod.rs b/src/watch/mod.rs
new file mode 100644
index 0000000..374c1d7
--- /dev/null
+++ b/src/watch/mod.rs
@@ -0,0 +1,118 @@
+// 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 anyhow::Result;
+use events::MpvEventHandler;
+use libmpv2::{events::EventContext, Mpv};
+use log::{debug, info, warn};
+
+use crate::{
+    app::App,
+    cache::maintain,
+    constants::{mpv_config_path, mpv_input_path},
+    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 = 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 = 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()
+    );
+
+    // There is nothing to watch
+    if play_things.len() == 0 {
+        return Ok(());
+    }
+
+    let mut playlist_cache: Vec<ExtractorHash> = Vec::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 cache_path = format!("\"{}\"", cache_path);
+
+        let args = &[&cache_path, "append-play"];
+
+        mpv.execute("loadfile", args)?;
+
+        playlist_cache.push(play_thing.extractor_hash);
+    }
+
+    let mut mpv_event_handler = MpvEventHandler::from_playlist(playlist_cache);
+    loop {
+        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(())
+}