]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
DVR: add local matches to dedup (title match makes no sense for all recs matches)
authorJaroslav Kysela <perex@perex.cz>
Wed, 6 Jan 2016 14:47:49 +0000 (15:47 +0100)
committerJaroslav Kysela <perex@perex.cz>
Wed, 6 Jan 2016 14:47:49 +0000 (15:47 +0100)
src/dvr/dvr.h
src/dvr/dvr_autorec.c
src/dvr/dvr_db.c

index 1ea2dc10c62e6a2b194cc1009bdb393e2fff1688..ce3e45c45f042697bff047a31a00560d887a0df3 100644 (file)
@@ -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;
 
 
index 43040e94a4a7fcde3ca80fc5c6092c4e5eafc2dd..56e4a3834a9a71ed3be94d07eab9b4fd1415f09f 100644 (file)
@@ -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);
 }
index aa21acb1d20b7c095999743a2ca6761c8b7baa04..35fcd59e80093e08a5ba131b5c340a993c61ee56 100644 (file)
@@ -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;
 }