From: Jaroslav Kysela Date: Wed, 6 Jan 2016 14:47:49 +0000 (+0100) Subject: DVR: add local matches to dedup (title match makes no sense for all recs matches) X-Git-Tag: v4.2.1~1205 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=66ad72055d07183b199d84ae934ad1b598e29acf;p=thirdparty%2Ftvheadend.git DVR: add local matches to dedup (title match makes no sense for all recs matches) --- diff --git a/src/dvr/dvr.h b/src/dvr/dvr.h index 1ea2dc10c..ce3e45c45 100644 --- a/src/dvr/dvr.h +++ b/src/dvr/dvr.h @@ -286,7 +286,12 @@ typedef enum { DVR_AUTOREC_RECORD_DIFFERENT_DESCRIPTION = 3, DVR_AUTOREC_RECORD_ONCE_PER_WEEK = 4, DVR_AUTOREC_RECORD_ONCE_PER_DAY = 5, - DVR_AUTOREC_RECORD_DIFFERENT_TITLE = 6, + DVR_AUTOREC_LRECORD_DIFFERENT_EPISODE_NUMBER = 6, + DVR_AUTOREC_LRECORD_DIFFERENT_TITLE = 7, + DVR_AUTOREC_LRECORD_DIFFERENT_SUBTITLE = 8, + DVR_AUTOREC_LRECORD_DIFFERENT_DESCRIPTION = 9, + DVR_AUTOREC_LRECORD_ONCE_PER_WEEK = 10, + DVR_AUTOREC_LRECORD_ONCE_PER_DAY = 11, } dvr_autorec_dedup_t; diff --git a/src/dvr/dvr_autorec.c b/src/dvr/dvr_autorec.c index 43040e94a..56e4a3834 100644 --- a/src/dvr/dvr_autorec.c +++ b/src/dvr/dvr_autorec.c @@ -920,18 +920,28 @@ dvr_autorec_entry_class_dedup_list ( void *o, const char *lang ) static const struct strtab tab[] = { { N_("Record all"), DVR_AUTOREC_RECORD_ALL }, - { N_("Record if different episode number"), + { N_("All: Record if different episode number"), DVR_AUTOREC_RECORD_DIFFERENT_EPISODE_NUMBER }, - { N_("Record if different title"), - DVR_AUTOREC_RECORD_DIFFERENT_TITLE }, - { N_("Record if different subtitle"), + { N_("All: Record if different subtitle"), DVR_AUTOREC_RECORD_DIFFERENT_SUBTITLE }, - { N_("Record if different description"), + { N_("All: Record if different description"), DVR_AUTOREC_RECORD_DIFFERENT_DESCRIPTION }, - { N_("Record once per week"), + { N_("All: Record once per week"), DVR_AUTOREC_RECORD_ONCE_PER_WEEK }, - { N_("Record once per day"), + { N_("All: Record once per day"), DVR_AUTOREC_RECORD_ONCE_PER_DAY }, + { N_("Local: Record if different episode number"), + DVR_AUTOREC_LRECORD_DIFFERENT_EPISODE_NUMBER }, + { N_("Local: Record if different title"), + DVR_AUTOREC_LRECORD_DIFFERENT_TITLE }, + { N_("Local: Record if different subtitle"), + DVR_AUTOREC_LRECORD_DIFFERENT_SUBTITLE }, + { N_("Local: Record if different description"), + DVR_AUTOREC_LRECORD_DIFFERENT_DESCRIPTION }, + { N_("Local: Record once per week"), + DVR_AUTOREC_LRECORD_ONCE_PER_WEEK }, + { N_("Local: Record once per day"), + DVR_AUTOREC_LRECORD_ONCE_PER_DAY }, }; return strtab2htsmsg(tab, 1, lang); } diff --git a/src/dvr/dvr_db.c b/src/dvr/dvr_db.c index aa21acb1d..35fcd59e8 100644 --- a/src/dvr/dvr_db.c +++ b/src/dvr/dvr_db.c @@ -1060,104 +1060,176 @@ not_so_good: return 0; } +/** + * + */ +typedef int (*_dvr_duplicate_fcn_t)(dvr_entry_t *de, dvr_entry_t *de2, void **aux); + +static int _dvr_duplicate_epnum(dvr_entry_t *de, dvr_entry_t *de2, void **aux) +{ + return !strempty(de2->de_episode) && !strcmp(de->de_episode, de2->de_episode); +} + +static int _dvr_duplicate_title(dvr_entry_t *de, dvr_entry_t *de2, void **aux) +{ + return !lang_str_compare(de->de_title, de2->de_title); +} + +static int _dvr_duplicate_subtitle(dvr_entry_t *de, dvr_entry_t *de2, void **aux) +{ + return !lang_str_compare(de->de_subtitle, de2->de_subtitle); +} + +static int _dvr_duplicate_desc(dvr_entry_t *de, dvr_entry_t *de2, void **aux) +{ + return !lang_str_compare(de->de_desc, de2->de_desc); +} + +static int _dvr_duplicate_per_week(dvr_entry_t *de, dvr_entry_t *de2, void **aux) +{ + struct tm *de1_start = *aux, de2_start; + if (de1_start == NULL) { + de1_start = calloc(1, sizeof(*de1_start)); + localtime_r(&de->de_start, de1_start); + de1_start->tm_mday -= (de1_start->tm_wday + 6) % 7; // week = mon-sun + mktime(de1_start); // adjusts de_start + *aux = de1_start; + } + localtime_r(&de2->de_start, &de2_start); + de2_start.tm_mday -= (de2_start.tm_wday + 6) % 7; // week = mon-sun + mktime(&de2_start); // adjusts de2_start + return de1_start->tm_year == de2_start.tm_year && + de1_start->tm_yday == de2_start.tm_yday; +} + +static int _dvr_duplicate_per_day(dvr_entry_t *de, dvr_entry_t *de2, void **aux) +{ + struct tm *de1_start = *aux, de2_start; + if (de1_start == NULL) { + de1_start = calloc(1, sizeof(*de1_start)); + localtime_r(&de->de_start, de1_start); + *aux = de1_start; + } + localtime_r(&de2->de_start, &de2_start); + return de1_start->tm_year == de2_start.tm_year && + de1_start->tm_yday == de2_start.tm_yday; +} + /** * */ static dvr_entry_t *_dvr_duplicate_event(dvr_entry_t *de) { + static _dvr_duplicate_fcn_t fcns[] = { + [DVR_AUTOREC_RECORD_DIFFERENT_EPISODE_NUMBER] = _dvr_duplicate_epnum, + [DVR_AUTOREC_LRECORD_DIFFERENT_EPISODE_NUMBER] = _dvr_duplicate_epnum, + [DVR_AUTOREC_LRECORD_DIFFERENT_TITLE] = _dvr_duplicate_title, + [DVR_AUTOREC_RECORD_DIFFERENT_SUBTITLE] = _dvr_duplicate_subtitle, + [DVR_AUTOREC_LRECORD_DIFFERENT_SUBTITLE] = _dvr_duplicate_subtitle, + [DVR_AUTOREC_RECORD_DIFFERENT_DESCRIPTION] = _dvr_duplicate_desc, + [DVR_AUTOREC_LRECORD_DIFFERENT_DESCRIPTION] = _dvr_duplicate_desc, + [DVR_AUTOREC_RECORD_ONCE_PER_WEEK] = _dvr_duplicate_per_week, + [DVR_AUTOREC_LRECORD_ONCE_PER_WEEK] = _dvr_duplicate_per_week, + [DVR_AUTOREC_RECORD_ONCE_PER_DAY] = _dvr_duplicate_per_day, + [DVR_AUTOREC_LRECORD_ONCE_PER_DAY] = _dvr_duplicate_per_day, + }; dvr_entry_t *de2; + _dvr_duplicate_fcn_t match; int record; + void *aux; if (!de->de_autorec) return NULL; + // title not defined, can't be deduped + if (lang_str_empty(de->de_title)) + return NULL; + record = de->de_autorec->dae_record; switch (record) { case DVR_AUTOREC_RECORD_ALL: return NULL; case DVR_AUTOREC_RECORD_DIFFERENT_EPISODE_NUMBER: + case DVR_AUTOREC_LRECORD_DIFFERENT_EPISODE_NUMBER: if (strempty(de->de_episode)) return NULL; break; - case DVR_AUTOREC_RECORD_DIFFERENT_TITLE: - break; case DVR_AUTOREC_RECORD_DIFFERENT_SUBTITLE: + case DVR_AUTOREC_LRECORD_DIFFERENT_SUBTITLE: if (lang_str_empty(de->de_subtitle)) return NULL; break; case DVR_AUTOREC_RECORD_DIFFERENT_DESCRIPTION: + case DVR_AUTOREC_LRECORD_DIFFERENT_DESCRIPTION: if (lang_str_empty(de->de_desc)) return NULL; break; case DVR_AUTOREC_RECORD_ONCE_PER_WEEK: + case DVR_AUTOREC_LRECORD_ONCE_PER_WEEK: + break; + case DVR_AUTOREC_LRECORD_DIFFERENT_TITLE: break; + default: + abort(); } - // title not defined, can't be deduped - if (lang_str_empty(de->de_title)) - return NULL; + match = fcns[record]; + aux = NULL; - LIST_FOREACH(de2, &dvrentries, de_global_link) { - if (de == de2) - continue; + assert(match); - // only earlier recordings qualify as master - if (de2->de_start > de->de_start) - continue; + if (record < DVR_AUTOREC_LRECORD_DIFFERENT_EPISODE_NUMBER) { + LIST_FOREACH(de2, &dvrentries, de_global_link) { + if (de == de2) + continue; - // only successful earlier recordings qualify as master - if (de2->de_sched_state == DVR_MISSED_TIME || - (de2->de_sched_state == DVR_COMPLETED && - de2->de_last_error != SM_CODE_OK)) - continue; + // only earlier recordings qualify as master + if (de2->de_start > de->de_start) + continue; - // if titles are not defined or do not match, don't dedup - if (record != DVR_AUTOREC_RECORD_DIFFERENT_TITLE && - lang_str_compare(de->de_title, de2->de_title)) - continue; + // only successful earlier recordings qualify as master + if (de2->de_sched_state == DVR_MISSED_TIME || + (de2->de_sched_state == DVR_COMPLETED && + de2->de_last_error != SM_CODE_OK)) + continue; - switch (record) { - case DVR_AUTOREC_RECORD_DIFFERENT_EPISODE_NUMBER: - if (!strempty(de2->de_episode) && !strcmp(de->de_episode, de2->de_episode)) - return de2; - break; - case DVR_AUTOREC_RECORD_DIFFERENT_TITLE: - if (!lang_str_compare(de->de_title, de2->de_title)) - return de2; - break; - case DVR_AUTOREC_RECORD_DIFFERENT_SUBTITLE: - if (!lang_str_compare(de->de_subtitle, de2->de_subtitle)) - return de2; - break; - case DVR_AUTOREC_RECORD_DIFFERENT_DESCRIPTION: - if (!lang_str_compare(de->de_desc, de2->de_desc)) - return de2; - break; - case DVR_AUTOREC_RECORD_ONCE_PER_WEEK: { - struct tm de1_start, de2_start; - localtime_r(&de->de_start, &de1_start); - localtime_r(&de2->de_start, &de2_start); - de1_start.tm_mday -= (de1_start.tm_wday + 6) % 7; // week = mon-sun - de2_start.tm_mday -= (de2_start.tm_wday + 6) % 7; // week = mon-sun - mktime(&de1_start); // adjusts de_start - mktime(&de2_start); // adjusts de2_start - if (de1_start.tm_year == de2_start.tm_year && - de1_start.tm_yday == de2_start.tm_yday) - return de2; - break; + // if titles are not defined or do not match, don't dedup + if (lang_str_compare(de->de_title, de2->de_title)) + continue; + + if (match(de, de2, &aux)) { + free(aux); + return de2; } - case DVR_AUTOREC_RECORD_ONCE_PER_DAY: { - struct tm de1_start, de2_start; - localtime_r(&de->de_start, &de1_start); - localtime_r(&de2->de_start, &de2_start); - if (de1_start.tm_year == de2_start.tm_year && - de1_start.tm_yday == de2_start.tm_yday) - return de2; - break; + } + } else { + LIST_FOREACH(de2, &de->de_autorec->dae_spawns, de_autorec_link) { + if (de == de2) + continue; + + // only earlier recordings qualify as master + if (de2->de_start > de->de_start) + continue; + + // only successful earlier recordings qualify as master + if (de2->de_sched_state == DVR_MISSED_TIME || + (de2->de_sched_state == DVR_COMPLETED && + de2->de_last_error != SM_CODE_OK)) + continue; + + // if titles are not defined or do not match, don't dedup + if (record != DVR_AUTOREC_LRECORD_DIFFERENT_TITLE && + lang_str_compare(de->de_title, de2->de_title)) + continue; + + if (match(de, de2, &aux)) { + free(aux); + return de2; } } } + free(aux); return NULL; }