about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--yt/src/watch/events/mod.rs50
-rw-r--r--yt/src/watch/mod.rs36
2 files changed, 70 insertions, 16 deletions
diff --git a/yt/src/watch/events/mod.rs b/yt/src/watch/events/mod.rs
index 413fb4b..d2a94a0 100644
--- a/yt/src/watch/events/mod.rs
+++ b/yt/src/watch/events/mod.rs
@@ -8,18 +8,14 @@
 // 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, HashSet},
-    time::Duration,
-};
+use std::collections::{HashMap, HashSet};
 
 use anyhow::{Context, Result};
 use libmpv2::{
     events::{Event, PlaylistEntryId},
     EndFileReason, Mpv,
 };
-use log::{debug, info, warn};
-use tokio::time;
+use log::{debug, info};
 
 use crate::{
     app::App,
@@ -37,6 +33,20 @@ use playlist_handler::PlaylistHandler;
 mod handlers;
 mod playlist_handler;
 
+#[derive(Debug, Clone, Copy)]
+pub enum IdleCheckOutput {
+    /// There are no videos already downloaded and no more marked to be watched.
+    /// Waiting is pointless.
+    NoMoreAvailable,
+
+    /// There are no videos cached, but some (>0) are marked to be watched.
+    /// So we should wait for them to become available.
+    NoCached { marked_watched: usize },
+
+    /// There are videos cached and ready to be inserted into the playback queue.
+    Available { newly_available: Option<usize> },
+}
+
 #[derive(Debug)]
 pub struct MpvEventHandler {
     watch_later_block_list: HashSet<ExtractorHash>,
@@ -210,19 +220,35 @@ impl MpvEventHandler {
     }
 
     /// Check if the playback queue is empty
-    pub async fn check_idle(&mut self, app: &App, mpv: &Mpv) -> Result<bool> {
+    pub async fn check_idle(&mut self, app: &App, mpv: &Mpv) -> Result<IdleCheckOutput> {
         if mpv.get_property::<bool>("idle-active")? {
-            warn!("There is nothing to watch yet. Will idle, until something is available");
+            // The playback is currently not running, but we might still have more videos lined up
+            // to be inserted into the queue.
+
             let number_of_new_videos = self.possibly_add_new_videos(app, mpv, false).await?;
 
             if number_of_new_videos == 0 {
-                time::sleep(Duration::from_secs(10)).await;
-                Ok(true)
+                let watch_videos = get_videos(app, &[VideoStatus::Watch], None).await?.len();
+
+                if watch_videos == 0 {
+                    // There are no more videos left. We should exit now.
+                    Ok(IdleCheckOutput::NoMoreAvailable)
+                } else {
+                    // There are still videos that *could* get downloaded. Wait for them.
+                    Ok(IdleCheckOutput::NoCached {
+                        marked_watched: watch_videos,
+                    })
+                }
             } else {
-                Ok(false)
+                Ok(IdleCheckOutput::Available {
+                    newly_available: Some(number_of_new_videos),
+                })
             }
         } else {
-            Ok(false)
+            // The playback is running. Obviously, something is available.
+            Ok(IdleCheckOutput::Available {
+                newly_available: None,
+            })
         }
     }
 
diff --git a/yt/src/watch/mod.rs b/yt/src/watch/mod.rs
index 5c76c12..6e7c372 100644
--- a/yt/src/watch/mod.rs
+++ b/yt/src/watch/mod.rs
@@ -8,12 +8,13 @@
 // 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 std::{collections::HashMap, time::Duration};
 
 use anyhow::{Context, Result};
-use events::MpvEventHandler;
+use events::{IdleCheckOutput, MpvEventHandler};
 use libmpv2::{events::EventContext, Mpv};
 use log::{debug, info, warn};
+use tokio::time;
 
 use crate::{
     app::App,
@@ -24,6 +25,7 @@ use crate::{
 
 pub mod events;
 
+#[allow(clippy::too_many_lines)]
 pub async fn watch(app: &App) -> Result<()> {
     maintain(app, false).await?;
 
@@ -107,8 +109,34 @@ pub async fn watch(app: &App) -> Result<()> {
     }
 
     let mut mpv_event_handler = MpvEventHandler::from_playlist(playlist_cache);
-    loop {
-        while mpv_event_handler.check_idle(app, &mpv).await? {}
+    let mut have_warned = (false, 0);
+    'watchloop: loop {
+        'waitloop: while let Ok(value) = mpv_event_handler.check_idle(app, &mpv).await {
+            match value {
+                IdleCheckOutput::NoMoreAvailable => {
+                    break 'watchloop;
+                }
+                IdleCheckOutput::NoCached { marked_watched } => {
+                    // try again next time.
+                    if have_warned.0 {
+                        if have_warned.1 != marked_watched {
+                            warn!("Now {} videos are marked as watched.", marked_watched);
+                            have_warned.1 = marked_watched;
+                        }
+                    } else {
+                        warn!("There is nothing to watch yet, but still {} videos marked as to be watched. \
+                        Will idle, until they become available", marked_watched);
+                        have_warned = (true, marked_watched);
+                    }
+                    time::sleep(Duration::from_secs(10)).await;
+                }
+                IdleCheckOutput::Available { newly_available: _ } => {
+                    have_warned.0 = false;
+                    // Something just became available!
+                    break 'waitloop;
+                }
+            }
+        }
 
         if let Some(ev) = ev_ctx.wait_event(600.) {
             match ev {