From: E.Smith <31170571+azlm8t@users.noreply.github.com> Date: Sun, 30 Sep 2018 20:45:21 +0000 (+0100) Subject: dvr: Pre-fetch fanart for upcoming recordings. X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ed31b3b31761aeb536164ca5c30c3e0f58b9890f;p=thirdparty%2Ftvheadend.git dvr: Pre-fetch fanart for upcoming recordings. 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. --- diff --git a/src/dvr/dvr.h b/src/dvr/dvr.h index 7aa605cc0..665171b25 100644 --- a/src/dvr/dvr.h +++ b/src/dvr/dvr.h @@ -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); diff --git a/src/dvr/dvr_db.c b/src/dvr/dvr_db.c index 513d828d0..3eeb94492 100644 --- a/src/dvr/dvr_db.c +++ b/src/dvr/dvr_db.c @@ -23,6 +23,7 @@ #include #include #include +#include #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 diff --git a/src/dvr/dvr_rec.c b/src/dvr/dvr_rec.c index 71e93a000..5dac2a628 100644 --- a/src/dvr/dvr_rec.c +++ b/src/dvr/dvr_rec.c @@ -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; diff --git a/src/string_list.c b/src/string_list.c index 27b87e019..000d9cc9d 100644 --- a/src/string_list.c +++ b/src/string_list.c @@ -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) { diff --git a/src/string_list.h b/src/string_list.h index 250139fcb..cc188d6eb 100644 --- a/src/string_list.h +++ b/src/string_list.h @@ -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)