]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
epggrab: manage multiple channel names for 'Auto EPG', fixes #3205
authorJaroslav Kysela <perex@perex.cz>
Mon, 26 Oct 2015 08:26:45 +0000 (09:26 +0100)
committerJaroslav Kysela <perex@perex.cz>
Mon, 26 Oct 2015 08:26:45 +0000 (09:26 +0100)
src/epggrab.h
src/epggrab/channel.c
src/epggrab/module/pyepg.c
src/epggrab/module/xmltv.c
src/epggrab/private.h
src/htsmsg.c
src/htsmsg.h

index b8327f2df79007b3441b6d5e9ad8c90780842cbd..db91bb145a2758b6db071f7b7ceecbbc08ebc400 100644 (file)
@@ -88,6 +88,8 @@ typedef struct epggrab_channel
   char                      *id;      ///< Grabber's ID
 
   char                      *name;    ///< Channel name
+  htsmsg_t                  *names;   ///< List of all channel names for grabber's ID
+  htsmsg_t                  *newnames;///< List of all channel names for grabber's ID (scan)
   char                      *icon;    ///< Channel icon
   char                      *comment; ///< Channel comment (EPG)
   int64_t                   lcn;      ///< Channel number (split)
index 3c5feffbe171add177cf1ef6d1d94727fc223842..feb892436750977d474faf94c42f7be1a1fa7815 100644 (file)
@@ -39,10 +39,18 @@ SKEL_DECLARE(epggrab_channel_skel, epggrab_channel_t);
 /* Check if channels match */
 int epggrab_channel_match ( epggrab_channel_t *ec, channel_t *ch )
 {
+  const char *chid, *s;
+  htsmsg_field_t *f;
+
   if (!ec || !ch || !ch->ch_epgauto || !ch->ch_enabled || !ec->enabled) return 0;
   if (LIST_FIRST(&ec->channels)) return 0; // ignore already paired
 
-  if (ec->name && !strcmp(ec->name, channel_get_epgid(ch))) return 1;
+  chid = channel_get_epgid(ch);
+  if (ec->name && !strcmp(ec->name, chid)) return 1;
+  if (ec->names)
+    HTSMSG_FOREACH(f, ec->names)
+      if ((s = htsmsg_field_get_str(f)) != NULL)
+        if (!strcmp(s, chid)) return 1;
   if (ec->lcn && ec->lcn == channel_get_number(ch)) return 1;
   return 0;
 }
@@ -127,7 +135,7 @@ int epggrab_channel_set_name ( epggrab_channel_t *ec, const char *name )
   channel_t *ch;
   int save = 0;
   if (!ec || !name) return 0;
-  if (!ec->name || strcmp(ec->name, name)) {
+  if (!ec->newnames && (!ec->name || strcmp(ec->name, name))) {
     if (ec->name) free(ec->name);
     ec->name = strdup(name);
     if (epggrab_conf.channel_rename) {
@@ -139,6 +147,9 @@ int epggrab_channel_set_name ( epggrab_channel_t *ec, const char *name )
     }
     save = 1;
   }
+  if (ec->newnames == NULL)
+    ec->newnames = htsmsg_create_list();
+  htsmsg_add_str(ec->newnames, NULL, name);
   return save;
 }
 
@@ -304,6 +315,8 @@ void epggrab_channel_destroy( epggrab_channel_t *ec, int delconf )
     hts_settings_remove("epggrab/%s/channels/%s",
                         ec->mod->saveid, idnode_uuid_as_sstr(&ec->idnode));
 
+  htsmsg_destroy(ec->newnames);
+  htsmsg_destroy(ec->names);
   free(ec->comment);
   free(ec->name);
   free(ec->icon);
@@ -319,6 +332,29 @@ void epggrab_channel_flush
     epggrab_channel_destroy(ec, delconf);
 }
 
+void epggrab_channel_begin_scan ( epggrab_module_t *mod )
+{
+  epggrab_channel_t *ec;
+  lock_assert(&global_lock);
+  RB_FOREACH(ec, &mod->channels, link)
+    if (ec->newnames) {
+      htsmsg_destroy(ec->newnames);
+      ec->newnames = NULL;
+    }
+}
+
+void epggrab_channel_end_scan ( epggrab_module_t *mod )
+{
+  epggrab_channel_t *ec;
+  lock_assert(&global_lock);
+  RB_FOREACH(ec, &mod->channels, link)
+    if (ec->newnames) {
+      htsmsg_destroy(ec->names);
+      ec->names = ec->newnames;
+      ec->newnames = NULL;
+    }
+}
+
 /* **************************************************************************
  * Global routines
  * *************************************************************************/
@@ -435,6 +471,30 @@ epggrab_channel_class_path_get ( void *obj )
   return &prop_sbuf_ptr;
 }
 
+static const void *
+epggrab_channel_class_names_get ( void *obj )
+{
+  epggrab_channel_t *ec = obj;
+  char *s = ec->names ? htsmsg_list_2_csv(ec->names, ',', 0) : NULL;
+  snprintf(prop_sbuf, PROP_SBUF_LEN, "%s", s ?: "");
+  free(s);
+  return &prop_sbuf_ptr;
+}
+
+static int
+epggrab_channel_class_names_set ( void *obj, const void *p )
+{
+  htsmsg_t *m = htsmsg_csv_2_list(p, ',');
+  epggrab_channel_t *ec = obj;
+  if (htsmsg_cmp(ec->names, m)) {
+    htsmsg_destroy(ec->names);
+    ec->names = m;
+  } else {
+    htsmsg_destroy(m);
+  }
+  return 0;
+}
+
 static const void *
 epggrab_channel_class_channels_get ( void *obj )
 {
@@ -508,6 +568,13 @@ const idclass_t epggrab_channel_class = {
       .name     = N_("Name"),
       .off      = offsetof(epggrab_channel_t, name),
     },
+    {
+      .type     = PT_STR,
+      .id       = "names",
+      .name     = N_("Names"),
+      .get      = epggrab_channel_class_names_get,
+      .set      = epggrab_channel_class_names_set,
+    },
     {
       .type     = PT_S64,
       .intsplit = CHANNEL_SPLIT,
index 3f5d5cb966f646dc99291caeb58e8a1a3c9c38bd..a606a1aedf6d1b2fa6a430931b1a1d8e72d9a510 100644 (file)
@@ -373,6 +373,10 @@ static int _pyepg_parse_epg
 
   if ((tags = htsmsg_get_map(data, "tags")) == NULL) return 0;
 
+  pthread_mutex_lock(&global_lock);
+  epggrab_channel_begin_scan(mod);
+  pthread_mutex_unlock(&global_lock);
+
   HTSMSG_FOREACH(f, tags) {
     save = 0;
     if (strcmp(f->hmf_name, "channel") == 0 ) {
@@ -403,6 +407,10 @@ static int _pyepg_parse_epg
     gsave |= save;
   }
 
+  pthread_mutex_lock(&global_lock);
+  epggrab_channel_end_scan(mod);
+  pthread_mutex_unlock(&global_lock);
+
   return gsave;
 }
 
index 04f28de10e122a41df21d1c4480c1df9a4dbf8d4..f8b00f7cd36a0b9091496f9195ad0cd344a69a59 100644 (file)
@@ -651,6 +651,10 @@ static int _xmltv_parse_tv
   if((tags = htsmsg_get_map(body, "tags")) == NULL)
     return 0;
 
+  pthread_mutex_lock(&global_lock);
+  epggrab_channel_begin_scan(mod);
+  pthread_mutex_unlock(&global_lock);
+
   HTSMSG_FOREACH(f, tags) {
     save = 0;
     if(!strcmp(f->hmf_name, "channel")) {
@@ -665,6 +669,11 @@ static int _xmltv_parse_tv
     }
     gsave |= save;
   }
+
+  pthread_mutex_lock(&global_lock);
+  epggrab_channel_end_scan(mod);
+  pthread_mutex_unlock(&global_lock);
+
   return gsave;
 }
 
index 970043b85ae356afa5651d34af8003103e3957d4..0fa93d73b795dcccac59aa3e28e3503973d356b0 100644 (file)
@@ -61,6 +61,10 @@ void epggrab_channel_destroy
   ( epggrab_channel_t *ec, int delconf );
 void epggrab_channel_flush
   ( epggrab_module_t *mod, int delconf );
+void epggrab_channel_begin_scan
+  ( epggrab_module_t *mod );
+void epggrab_channel_end_scan
+  ( epggrab_module_t *mod );
 
 void epggrab_channel_init(void);
 void epggrab_channel_done(void);
index 792f99ab8f7c4a9504eae0701a222211a411e7c1..0c89f7a46ec1773762d7fc81b95195b193dee2e7 100644 (file)
@@ -937,6 +937,71 @@ htsmsg_copy(htsmsg_t *src)
   return dst;
 }
 
+/**
+ *
+ */
+int
+htsmsg_cmp(htsmsg_t *m1, htsmsg_t *m2)
+{
+  htsmsg_field_t *f1, *f2;
+
+  if (m1 == NULL && m2 == NULL)
+    return 0;
+  if (m1 == NULL || m2 == NULL)
+    return 1;
+
+  f2 = TAILQ_FIRST(&m2->hm_fields);
+  TAILQ_FOREACH(f1, &m1->hm_fields, hmf_link) {
+
+    if (f1->hmf_type != f2->hmf_type)
+      return 1;
+    if (strcmp(f1->hmf_name ?: "", f2->hmf_name ?: ""))
+      return 1;
+
+    switch(f1->hmf_type) {
+
+    case HMF_MAP:
+    case HMF_LIST:
+      if (htsmsg_cmp(&f1->hmf_msg, &f2->hmf_msg))
+        return 1;
+      break;
+      
+    case HMF_STR:
+      if (strcmp(f1->hmf_str, f2->hmf_str))
+        return 1;
+      break;
+
+    case HMF_S64:
+      if (f1->hmf_s64 != f2->hmf_s64)
+        return 1;
+      break;
+
+    case HMF_BOOL:
+      if (f1->hmf_bool != f2->hmf_bool)
+        return 1;
+      break;
+
+    case HMF_BIN:
+      if (f1->hmf_binsize != f2->hmf_binsize)
+        return 1;
+      if (memcmp(f1->hmf_bin, f2->hmf_bin, f1->hmf_binsize))
+        return 1;
+      break;
+
+    case HMF_DBL:
+      if (f1->hmf_dbl != f2->hmf_dbl)
+        return 1;
+      break;
+    }
+
+    f2 = TAILQ_NEXT(f2, hmf_link);
+  }
+
+  if (f2)
+    return 1;
+  return 0;
+}
+
 /**
  *
  */
@@ -1004,12 +1069,11 @@ htsmsg_list_2_csv(htsmsg_t *m, char delim, int human)
   if (human) {
     sep[0] = delim;
     sep[1] = ' ';
-    sep[2] = '\0';
-    ssep = "\"";
+    ssep = "";
   } else {
     sep[0] = delim;
     sep[1] = '\0';
-    ssep = "";
+    ssep = "\"";
   }
   HTSMSG_FOREACH(f, m) {
     if (f->hmf_type == HMF_STR) {
index 334cfc6010e47a2fbd39d987ee3d70dc19199de1..78fcf8e7801d7348312d4bb003d0003973f25fc1 100644 (file)
@@ -389,6 +389,11 @@ htsmsg_field_t *htsmsg_field_last(htsmsg_t *msg);
  */
 htsmsg_t *htsmsg_copy(htsmsg_t *src);
 
+/**
+ * Compare a message.
+ */
+int htsmsg_cmp(htsmsg_t *m1, htsmsg_t *m2);
+
 #define HTSMSG_FOREACH(f, msg) TAILQ_FOREACH(f, &(msg)->hm_fields, hmf_link)