]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
dvr: Pre-fetch fanart for upcoming recordings.
authorE.Smith <31170571+azlm8t@users.noreply.github.com>
Sun, 30 Sep 2018 20:45:21 +0000 (21:45 +0100)
committerperexg <perex@perex.cz>
Tue, 2 Oct 2018 14:05:03 +0000 (16:05 +0200)
We keep track of uuids for upcoming recordings. Once an hour we
get one entry from the list and pre-fetch artwork for it so it
can be displayed in the UI "upcoming recordings" dialog.

This is only done if the user has explicitly enabled fetch
artwork on the entry's profile.

src/dvr/dvr.h
src/dvr/dvr_db.c
src/dvr/dvr_rec.c
src/string_list.c
src/string_list.h

index 7aa605cc0451a88fb81a395f63a528378dfa3a42..665171b2583cb16a6ab065a97f5c0b816b8e8dbd 100644 (file)
@@ -649,6 +649,8 @@ int dvr_entry_verify(dvr_entry_t *de, access_t *a, int readonly);
 void dvr_entry_changed(dvr_entry_t *de);
 
 void dvr_spawn_cmd(dvr_entry_t *de, const char *cmd, const char *filename, int pre);
+/// Spawn a fetch of artwork for the entry.
+void dvr_spawn_fetch_artwork(dvr_entry_t *de);
 
 void dvr_vfs_refresh_entry(dvr_entry_t *de);
 void dvr_vfs_remove_entry(dvr_entry_t *de);
index 513d828d0f4676ec2e1252450708fade481e185f..3eeb94492ff0feec9817253b1f26a323f09efe0c 100644 (file)
@@ -23,6 +23,7 @@
 #include <assert.h>
 #include <string.h>
 #include <ctype.h>
+#include <string_list.h>
 
 #include "settings.h"
 
@@ -44,6 +45,9 @@ static int dvr_in_init;
 #if ENABLE_DBUS_1
 static mtimer_t dvr_dbus_timer;
 #endif
+/// Periodically pre-fetch artwork for scheduled recordings.
+static mtimer_t dvr_fanart_timer;
+static string_list_t *dvr_fanart_to_prefetch;
 
 static void dvr_entry_deferred_destroy(dvr_entry_t *de);
 static void dvr_entry_set_timer(dvr_entry_t *de);
@@ -757,6 +761,53 @@ dvr_usage_count(access_t *aa)
   return used;
 }
 
+/// Add the entry details to a list of fanart to prefetch.
+/// We then periodically check the list to update artwork.
+/// We don't do the check too frequently since most providers
+/// have limits on how frequently artwork can be fetched.
+/// It doesn't matter if the entry gets deleted before we
+/// perform the check.
+static void
+dvr_entry_fanart_add_to_prefetch(const dvr_entry_t *de)
+{
+  char ubuf[UUID_HEX_SIZE];
+  if (!de || !de->de_enabled)
+    return;
+  /*  Nothing to do if we have images already */
+  if (de->de_image && de->de_fanart_image)
+    return;
+  /* User doesn't want us to fetch artwork */
+  if (de->de_config && !de->de_config->dvr_fetch_artwork)
+    return;
+
+  string_list_insert(dvr_fanart_to_prefetch,
+                     idnode_uuid_as_str(&de->de_id, ubuf));
+}
+
+static void
+dvr_entry_fanart_prefetch_cb(void *aux)
+{
+  lock_assert(&global_lock);
+
+  /* Only do one entry, even if list has many since we don't
+   * want to overload fanart providers.
+   */
+  char *id = string_list_remove_first(dvr_fanart_to_prefetch);
+  if (id) {
+    dvr_entry_t *de = dvr_entry_find_by_uuid(id);
+    if (de && de->de_config && de->de_config->dvr_fetch_artwork) {
+      tvhinfo(LS_DVR, "Prefetching artwork for %s \"%s\"", id, lang_str_get(de->de_title, NULL));
+      dvr_spawn_fetch_artwork(de);
+    }
+
+    free(id);
+  }
+
+  // Re-arm timer with a slight random factor to avoid queries at same
+  // time every hour.
+  mtimer_arm_rel(&dvr_fanart_timer, dvr_entry_fanart_prefetch_cb, NULL, sec2mono(3600 + random() % 900));
+}
+
 void
 dvr_entry_set_timer(dvr_entry_t *de)
 {
@@ -811,6 +862,7 @@ recording:
 
     dvr_entry_trace_time1(de, "start", start, "set timer - schedule");
     gtimer_arm_absn(&de->de_timer, dvr_timer_start_recording, de, start);
+    dvr_entry_fanart_add_to_prefetch(de);
 #if ENABLE_DBUS_1
     mtimer_arm_rel(&dvr_dbus_timer, dvr_dbus_timer_cb, NULL, sec2mono(5));
 #endif
@@ -4732,6 +4784,7 @@ dvr_entry_init(void)
   dvr_entry_t *de1, *de2;
 
   dvr_in_init = 1;
+  dvr_fanart_to_prefetch = string_list_create();
   idclass_register(&dvr_entry_class);
   rere = htsmsg_create_map();
   /* load config, but remove parent/child fields */
@@ -4767,6 +4820,10 @@ dvr_entry_init(void)
     de2 = LIST_NEXT(de1, de_global_link);
     dvr_entry_set_timer(de1);
   }
+
+  // After a while we get one new entry and prefetch artwork for an
+  // upcoming dvr entry.
+  mtimer_arm_rel(&dvr_fanart_timer, dvr_entry_fanart_prefetch_cb, NULL, sec2mono(3600));
 }
 
 void
index 71e93a0004931df3ea86236161894c935be6f322..5dac2a628486b57a2521254702972c0b09ab0921 100644 (file)
@@ -58,7 +58,7 @@ static const int prio2weight[6] = {
 };
 
 /// Spawn a fetch of artwork for the entry.
-static void
+void
 dvr_spawn_fetch_artwork(dvr_entry_t *de)
 {
   const dvr_config_t *cfg;
index 27b87e019412fc123d109787285acc960c6fec09..000d9cc9d498c3748a40ec687dc2682065bb3adb 100644 (file)
@@ -50,6 +50,20 @@ string_list_destroy(string_list_t *l)
   free(l);
 }
 
+char *
+string_list_remove_first(string_list_t *l)
+{
+  char *ret = NULL;
+  if (!l) return NULL;
+  string_list_item_t *item = RB_FIRST(l);
+  if (!item)
+    return NULL;
+  ret = item->id;
+  RB_REMOVE(l, item, h_link);
+  free(item);
+  return ret;
+}
+
 static inline int
 string_list_item_cmp(const void *a, const void *b)
 {
index 250139fcb47ea94092da30702fb7e1e38b42ab55..cc188d6eb2cee31a45140e3cbef47a5f13b0f3c1 100644 (file)
@@ -60,6 +60,11 @@ void string_list_insert(string_list_t *l, const char *id);
 /// Insert a copy of lowercase id in to the sorted string list.
 void string_list_insert_lowercase(string_list_t *l, const char *id);
 
+/// Remove the first entry from the list and return ownership to the
+/// caller.
+char *string_list_remove_first(string_list_t *l)
+  __attribute__((warn_unused_result));
+
 /// Conversion function from sorted string list to an htsmsg.
 /// @return NULL if empty.
 struct htsmsg *string_list_to_htsmsg(const string_list_t *l)