]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
eit: recoded - use a config file to configure all grabbers
authorJaroslav Kysela <perex@perex.cz>
Mon, 5 Feb 2018 19:35:50 +0000 (20:35 +0100)
committerJaroslav Kysela <perex@perex.cz>
Mon, 5 Feb 2018 20:03:39 +0000 (21:03 +0100)
data/conf/epggrab/eit/config [new file with mode: 0644]
src/epggrab/module/eit.c
src/htsmsg.c
src/htsmsg.h

diff --git a/data/conf/epggrab/eit/config b/data/conf/epggrab/eit/config
new file mode 100644 (file)
index 0000000..e497007
--- /dev/null
@@ -0,0 +1,106 @@
+{
+
+  "uk_freesat": {
+    "name": {
+      "eng": "UK: Freesat"
+    },
+    "prio": 5,
+    "pid": 3003,
+    "conv": "huffman",
+    "nit": {
+      "Freesat": 1
+    },
+    "priv": 1179861332,
+    "hacks": {
+       "bat": { "pid": 3002 },
+       "interest-4e": 1
+    }
+  },
+
+  "uk_freeview": {
+    "name": {
+      "eng": "UK: Freeview"
+    },
+    "nit": {
+      "FIXMEFIXME": 1
+    },
+    "prio": 5,
+    "conv": "huffman"
+  },
+
+  "nz_freeview2": {
+    "name": {
+      "eng": "New Zealand: Freeview Local"
+    },
+    "nit": {
+      "Freeview ": {
+        "onid": 8746,
+        "nbid": [ 13313, 13314, 13315, 13316 ],
+        "tsid": [ 26, 27, 28, 31, 32 ]
+      }
+    },
+    "prio": 5,
+    "conv": "huffman",
+    "hacks": {
+      "svc-net-lookup": 1
+    }
+  },
+
+  "nz_freeview1": {
+    "name": {
+      "eng": "New Zealand: Freeview Base"
+    },
+    "nit": {
+      "Freeview ": {
+        "onid": 8746,
+        "nbid": [ 13313, 13314, 13315, 13316 ]
+      }
+    },
+    "prio": 1,
+    "conv": "huffman"
+  },
+
+  "viasat_baltic": {
+    "name": {
+      "eng": "VIASAT: Baltic"
+    },
+    "nit": {
+      "Sirius": { "nbid": 85 },
+      "Viasat": { "nbid": 86 }
+    },
+    "prio": 5
+  },
+
+  "Bulsatcom_39E": {
+    "name": {
+      "eng": "Bulsatcom: Bula 39E"
+    },
+    "nit": {
+      "FIXMEFIXME": 1
+    },
+    "pid": 299,
+    "prio": 5
+  },
+
+  "uk_cable_virgin": {
+    "name": {
+      "eng": "UK: Cable Virgin"
+    },
+    "nit": {
+      "FIXMEFIXME": 1
+    },
+    "pid": 700,
+    "prio": 5,
+    "hacks": {
+       "extra-mux-lookup": 1
+    }
+  },
+
+  "eit": {
+    "name": {
+      "eng": "EIT: EPG Grabber"
+    },
+    "prio": 1
+  }
+
+}
index 140532d51e79d836766ae4b4b0cf3f3cdfb91421..be4420a4d0c515776b807c5b58faf8947c861de7 100644 (file)
  * Opaque
  * ***********************************************************************/
 
+typedef struct eit_nit {
+  LIST_ENTRY(eit_nit) link;
+  char *name;
+  uint16_t onid[32];
+  uint16_t tsid[32];
+  uint16_t nbid[32];
+  int onid_count;
+  int tsid_count;
+  int nbid_count;
+} eit_nit_t;
+
 typedef struct eit_private
 {
-  int  id;
+  LIST_ENTRY(eit_private) link;
   uint16_t pid;
-  int  conv;
-  int  spec;
+  uint16_t bat_pid;
+  int conv;
+  uint32_t hacks;
+  uint32_t nitpriv;
+  LIST_HEAD(, eit_nit) nit;
+  epggrab_ota_module_ops_t *ops;
 } eit_private_t;
 
-#define EIT_ID_STANDARD             0
-#define EIT_ID_UK_FREESAT           1
-#define EIT_ID_UK_FREEVIEW          2
-#define EIT_ID_NZ_FREEVIEW1         3
-#define EIT_ID_NZ_FREEVIEW2         4
-#define EIT_ID_BALTIC               5
-#define EIT_ID_BULSAT               6
-#define EIT_ID_UK_CABLE_VIRGIN      7
-
 #define EIT_CONV_HUFFMAN            1
 
-#define EIT_SPEC_UK_FREESAT         1
-#define EIT_SPEC_NZ_FREEVIEW        2
-#define EIT_SPEC_UK_CABLE_VIRGIN    3
+#define EIT_HACK_INTEREST4E         (1<<0)
+#define EIT_HACK_EXTRAMUXLOOKUP     (1<<1)
+#define EIT_HACK_SVCNETLOOKUP       (1<<2)
 
 /* Queued data structure */
 typedef struct eit_data
@@ -919,10 +925,10 @@ static int
 _eit_callback
   (mpegts_table_t *mt, const uint8_t *ptr, int len, int tableid)
 {
-  int r, sect, last, ver, spec;
+  int r, sect, last, ver;
   uint8_t  seg;
   uint16_t onid, tsid, sid;
-  uint32_t extraid;
+  uint32_t extraid, hacks;
   mpegts_service_t     *svc;
   mpegts_mux_t         *mm;
   epggrab_ota_map_t    *map;
@@ -940,7 +946,7 @@ _eit_callback
   mm  = mt->mt_mux;
   map = mt->mt_opaque;
   mod = (epggrab_module_t *)map->om_module;
-  spec = ((eit_private_t *)((epggrab_module_ota_t *)mod)->opaque)->spec;
+  hacks = ((eit_private_t *)((epggrab_module_ota_t *)mod)->opaque)->hacks;
 
   /* Statistics */
   ths = mpegts_mux_find_subscription_by_name(mm, "epggrab");
@@ -969,7 +975,7 @@ _eit_callback
 
   /* Register interest */
   if (tableid == 0x4e || (tableid >= 0x50 && tableid < 0x60) ||
-      spec == EIT_SPEC_UK_FREESAT /* uk_freesat hack */)
+      (hacks & EIT_HACK_INTEREST4E) != 0 /* uk_freesat hack */)
     ota = epggrab_ota_register((epggrab_module_ota_t*)mod, NULL, mm);
 
   /* Begin */
@@ -989,7 +995,7 @@ _eit_callback
   
   /* UK Cable Virgin: EPG data for services in other transponders is transmitted 
   // in the 'actual' transpoder table IDs */
-  if (spec == EIT_SPEC_UK_CABLE_VIRGIN && (tableid == 0x50 || tableid == 0x4E)) {
+  if ((hacks & EIT_HACK_EXTRAMUXLOOKUP) != 0 && (tableid == 0x50 || tableid == 0x4E)) {
     mm = mpegts_network_find_mux(mm->mm_network, onid, tsid, 1);
   }
   if(!mm)
@@ -1018,8 +1024,7 @@ _eit_callback
   svc = mpegts_mux_find_service(mm, sid);
   if (!svc) {
     /* NZ Freesat: use main data */
-    if (spec == EIT_SPEC_NZ_FREEVIEW && onid == 0x222a &&
-        (tsid == 0x19 || tsid == 0x1d)) {
+    if (hacks & EIT_HACK_SVCNETLOOKUP) {
       svc = mpegts_network_find_active_service(mm->mm_network, sid, &mm);
       if (svc)
         goto svc_ok;
@@ -1167,19 +1172,16 @@ static int _eit_tune
   return r;
 }
 
-#define PRIV_FSAT (('F' << 24) | ('S' << 16) | ('A' << 8) | 'T')
-
-static epggrab_ota_map_t *eit_find_epggrab_map(epggrab_ota_mux_t *om, int id)
+static int eit_nit_array_check(uint16_t val, uint16_t *array, int array_count)
 {
-  epggrab_ota_map_t *map;
-  epggrab_module_ota_t *m;
+  int i;
 
-  LIST_FOREACH(map, &om->om_modules, om_link) {
-    m = map->om_module;
-    if (m->opaque && ((eit_private_t *)m->opaque)->id == id)
-      return map;
-  }
-  return NULL;
+  if (array_count <= 0)
+    return 0;
+  for (i = 0; i < array_count; i++)
+    if (array[i] == val)
+      return 0;
+  return 1;
 }
 
 void eit_nit_callback(mpegts_table_t *mt, uint16_t nbid, const char *name, uint32_t nitpriv)
@@ -1188,48 +1190,51 @@ void eit_nit_callback(mpegts_table_t *mt, uint16_t nbid, const char *name, uint3
   epggrab_ota_mux_t *om = epggrab_ota_find_mux(dm);
   epggrab_ota_map_t *map;
   epggrab_module_ota_t *m = NULL;
+  eit_nit_t *nit;
   eit_private_t *priv = NULL;
-  int id = EIT_ID_STANDARD, pid, opts = 0;
+  int pid, opts = 0;
 
   tvhtrace(LS_TBL_EIT, "NIT - tsid %04X (%d) onid %04X (%d) nbid %04X (%d) network name '%s' private %08X",
            dm->mm_tsid, dm->mm_tsid, dm->mm_onid, dm->mm_onid, nbid, nbid, name, nitpriv);
 
-  if (nitpriv == PRIV_FSAT && strcmp(name, "Freesat") == 0) {
-    id = EIT_ID_UK_FREESAT;
-    /* always use BAT when UK Freesat detected */
-    mpegts_table_add(dm, DVB_BAT_BASE, DVB_BAT_MASK, dvb_bat_callback, NULL,
-                     "fsat-bat", LS_TBL_BASE, MT_CRC, 3002, MPS_WEIGHT_EIT);
-  } else if ((strcmp(name, "Sirius") == 0 && nbid == 0x55) ||
-             (strcmp(name, "Viasat") == 0 && nbid == 0x56)) {
-    id = EIT_ID_BALTIC;
-  } else if (strcmp(name, "Freeview ") == 0 && dm->mm_onid == 0x222a &&
-           nbid >= 0x3401 && nbid < 0x3500) {
-    id = EIT_ID_NZ_FREEVIEW1;
-    if ((dm->mm_tsid > 0x19 && dm->mm_tsid < 0x1d) ||
-        (dm->mm_tsid > 0x1e && dm->mm_tsid < 0x21))
-      id = EIT_ID_NZ_FREEVIEW2;
-  }
-
-  while (1) {
-    map = eit_find_epggrab_map(om, id);
-    if (map == NULL)
-      return;
-
+  LIST_FOREACH(map, &om->om_modules, om_link) {
     m = map->om_module;
-    if (!m->enabled && !map->om_forced) {
-      if (id != EIT_ID_STANDARD) {
-        if (id == EIT_ID_NZ_FREEVIEW2)
-          id = EIT_ID_NZ_FREEVIEW1;
-        else
-          id = EIT_ID_STANDARD;
-        continue;
+    priv = m->opaque;
+    if (priv == NULL)
+      continue;
+    if (priv->nitpriv && priv->nitpriv != nitpriv)
+      continue;
+    if (LIST_FIRST(&priv->nit)) {
+      LIST_FOREACH(nit, &priv->nit, link) {
+        if (nit->name && strcmp(nit->name, name))
+          continue;
+        if (eit_nit_array_check(dm->mm_onid, nit->onid, nit->onid_count))
+          continue;
+        if (eit_nit_array_check(dm->mm_tsid, nit->tsid, nit->tsid_count))
+          continue;
+        if (eit_nit_array_check(nbid, nit->nbid, nit->nbid_count))
+          continue;
+        break;
       }
-      return;
+      if (nit)
+        break;
+    } else {
+      break;
     }
+  }
 
-    break;
+  if (map && priv->bat_pid) {
+    mpegts_table_add(dm, DVB_BAT_BASE, DVB_BAT_MASK, dvb_bat_callback, NULL,
+                     "ebat", LS_TBL_BASE, MT_CRC, priv->bat_pid, MPS_WEIGHT_EIT);
   }
 
+  if (!map)
+    return;
+
+  m = map->om_module;
+  if (!m->enabled && !map->om_forced)
+    return;
+
   tvhtrace(m->subsys, "NIT - detected module '%s'", m->id);
   priv = (eit_private_t *)m->opaque;
   pid = priv->pid;
@@ -1333,6 +1338,22 @@ static void _eit_module_load_config(eit_module_t *mod)
     free(generic_name);
 }
 
+void _eit_done ( void *m )
+{
+  eit_module_t *mod = m;
+  eit_nit_t *nit;
+  eit_private_t *priv = mod->opaque;
+  _eit_scrape_clear(mod);
+  mod->opaque = NULL;
+  while ((nit = LIST_FIRST(&priv->nit)) != NULL) {
+    LIST_REMOVE(nit, link);
+    free(nit->name);
+    free(nit);
+  }
+  free(priv->ops);
+  free(priv);
+}
+
 static htsmsg_t *
 epggrab_mod_eit_class_short_list ( void *o, const char *lang )
 {
@@ -1386,50 +1407,110 @@ static eit_module_t *eit_module_ota_create
   return mod;
 }
 
-#define EIT_OPS(name, _id, _pid, _conv, _spec) \
-  static eit_private_t opaque_##name = { \
-    .id = (_id), \
-    .pid = (_pid), \
-    .conv = (_conv), \
-    .spec = (_spec), \
-  }; \
-  static epggrab_ota_module_ops_t name = { \
-    .start  = _eit_start, \
-    .done = _eit_done, \
-    .activate = _eit_activate, \
-    .process_data = _eit_process_data, \
-    .tune   = _eit_tune, \
-    .opaque = &opaque_##name, \
+static void eit_parse_list
+  ( htsmsg_t *conf, const char *fname, uint16_t *list, int list_len, int *count )
+{
+  htsmsg_t *l = htsmsg_get_list(conf, fname);
+  htsmsg_field_t *f;
+  int val;
+  *count = 0;
+  if (l == 0) {
+    val = htsmsg_get_s32_or_default(conf, fname, -1);
+    if (val >= 0) {
+      list[0] = val;
+      *count = 1;
+    }
+    return;
   }
+  HTSMSG_FOREACH(f, l) {
+    if (!htsmsg_field_get_s32(f, &val) && val >= 0 && val < 65536) {
+      *list++ = val;
+      (*count)++;
+      list_len--;
+    }
+    if (list_len == 0)
+      break;
+  }
+}
 
-#define EIT_CREATE(id, name, prio, ops) \
-  eit_module_ota_create(id, LS_TBL_EIT, NULL, name, prio, ops)
-
-void eit_init ( void )
+static void eit_init_one ( const char *id, htsmsg_t *conf )
 {
-  EIT_OPS(ops, EIT_ID_STANDARD, 0, 0, 0);
-  EIT_OPS(ops_uk_freesat, EIT_ID_UK_FREESAT, 3003, EIT_CONV_HUFFMAN, EIT_SPEC_UK_FREESAT);
-  EIT_OPS(ops_uk_freeview, EIT_ID_UK_FREEVIEW, 0, EIT_CONV_HUFFMAN, 0);
-  EIT_OPS(ops_nz_freeview1, EIT_ID_NZ_FREEVIEW1, 0, EIT_CONV_HUFFMAN, EIT_SPEC_NZ_FREEVIEW);
-  EIT_OPS(ops_nz_freeview2, EIT_ID_NZ_FREEVIEW2, 0, EIT_CONV_HUFFMAN, EIT_SPEC_NZ_FREEVIEW);
-  EIT_OPS(ops_baltic, EIT_ID_BALTIC, 0x39, 0, 0);
-  EIT_OPS(ops_bulsat, EIT_ID_BULSAT, 0x12b, 0, 0);
-  EIT_OPS(ops_uk_cable_virgin, EIT_ID_UK_CABLE_VIRGIN, 0x2bc, 0, EIT_SPEC_UK_CABLE_VIRGIN);
-
-  EIT_CREATE("eit", "EIT: DVB Grabber", 1, &ops);
-  EIT_CREATE("uk_freesat", "UK: Freesat", 5, &ops_uk_freesat);
-  EIT_CREATE("uk_freeview", "UK: Freeview", 5, &ops_uk_freeview);
-  EIT_CREATE("nz_freeview1", "New Zealand: Freeview Base", 1, &ops_nz_freeview1);
-  EIT_CREATE("nz_freeview2", "New Zealand: Freeview Local", 5, &ops_nz_freeview2);
-  EIT_CREATE("viasat_baltic", "VIASAT: Baltic", 5, &ops_baltic);
-  EIT_CREATE("Bulsatcom_39E", "Bulsatcom: Bula 39E", 5, &ops_bulsat);
-  EIT_CREATE("uk_cable_virgin", "UK: Cable Virgin", 5, &ops_uk_cable_virgin);
+  epggrab_ota_module_ops_t *ops;
+  eit_private_t *priv;
+  eit_nit_t *nit;
+  const char *s;
+  htsmsg_t *map, *e;
+  htsmsg_field_t *f;
+  int prio = htsmsg_get_s32_or_default(conf, "prio", 1);
+  lang_str_t *name_str = lang_str_deserialize(conf, "name");
+
+  ops = calloc(1, sizeof(*ops));
+  priv = calloc(1, sizeof(*priv));
+  ops->start = _eit_start;
+  ops->done = _eit_done;
+  ops->activate = _eit_activate;
+  ops->process_data = _eit_process_data;
+  ops->tune = _eit_tune;
+  ops->opaque = priv;
+  priv->ops = ops;
+  priv->pid = htsmsg_get_s32_or_default(conf, "pid", 0);
+  s = htsmsg_get_str(conf, "conv");
+  if (s && strcmp(s, "huffman") == 0)
+    priv->conv = EIT_CONV_HUFFMAN;
+  priv->nitpriv = htsmsg_get_u32_or_default(conf, "priv", 0);
+  map = htsmsg_get_map(conf, "nit");
+  if (map) {
+    HTSMSG_FOREACH(f, map) {
+      nit = calloc(1, sizeof(*nit));
+      nit->name = strdup(f->hmf_name);
+      if ((e = htsmsg_field_get_map(f)) != NULL) {
+        eit_parse_list(e, "onid", nit->onid, ARRAY_SIZE(nit->onid), &nit->onid_count);
+        eit_parse_list(e, "tsid", nit->tsid, ARRAY_SIZE(nit->tsid), &nit->tsid_count);
+        eit_parse_list(e, "nbid", nit->nbid, ARRAY_SIZE(nit->nbid), &nit->nbid_count);
+      }
+      LIST_INSERT_HEAD(&priv->nit, nit, link);
+    }
+  }
+  map = htsmsg_get_map(conf, "hacks");
+  if (map) {
+    HTSMSG_FOREACH(f, map) {
+      if (strcmp(f->hmf_name, "interest-4e") == 0)
+        priv->hacks |= EIT_HACK_INTEREST4E;
+      else if (strcmp(f->hmf_name, "extra-mux-lookup") == 0)
+        priv->hacks |= EIT_HACK_EXTRAMUXLOOKUP;
+      else if (strcmp(f->hmf_name, "svc-net-lookup") == 0)
+        priv->hacks |= EIT_HACK_EXTRAMUXLOOKUP;
+      else if (strcmp(f->hmf_name, "bat") == 0) {
+        if (!(e = htsmsg_field_get_map(f))) continue;
+        priv->bat_pid = htsmsg_get_s32_or_default(e, "pid", 0);
+      }
+    }
+  }
+  if (name_str) {
+    eit_module_ota_create(id, LS_TBL_EIT, NULL,
+                          lang_str_get(name_str, NULL),
+                          prio, ops);
+  } else {
+    tvherror(LS_TBL_EIT, "missing name for '%s' in config", id);
+  }
+  lang_str_destroy(name_str);
 }
 
-void _eit_done ( void *m )
+void eit_init ( void )
 {
-  eit_module_t *mod = m;
-  _eit_scrape_clear(mod);
+  htsmsg_field_t *f;
+  htsmsg_t *c, *e;
+
+  c = hts_settings_load("epggrab/eit/config");
+  if (!c) {
+    tvhwarn(LS_TBL_EIT, "EIT configuration file missing");
+    return;
+  }
+  HTSMSG_FOREACH(f, c) {
+    if (!(e = htsmsg_field_get_map(f))) continue;
+    eit_init_one(f->hmf_name, e);
+  }
+  htsmsg_destroy(c);
 }
 
 void eit_done ( void )
index 40a5cbbf7a5b6b6da6bfdf04f1f12b4dfd21c555..e29130a3674c5c2c04703e68493808dfdcfdf4da 100644 (file)
@@ -805,7 +805,6 @@ htsmsg_get_u32_or_default(htsmsg_t *msg, const char *name, uint32_t def)
   return htsmsg_get_u32(msg, name, &u32) ? def : u32;
 }
 
-
 /**
  *
  */
@@ -816,8 +815,6 @@ htsmsg_get_s32_or_default(htsmsg_t *msg, const char *name, int32_t def)
   return htsmsg_get_s32(msg, name, &s32) ? def : s32;
 }
 
-
-
 /*
  *
  */
@@ -832,11 +829,29 @@ htsmsg_get_s32(htsmsg_t *msg, const char *name, int32_t *s32p)
 
   if(s64 < -0x80000000LL || s64 > 0x7fffffffLL)
     return HTSMSG_ERR_CONVERSION_IMPOSSIBLE;
-  
+
   *s32p = s64;
   return 0;
 }
 
+/*
+ *
+ */
+int
+htsmsg_field_get_s32(htsmsg_field_t *f, int32_t *s32p)
+{
+  int r;
+  int64_t s64;
+
+  if((r = htsmsg_field_get_s64(f, &s64)) != 0)
+    return r;
+
+  if(s64 < -0x80000000LL || s64 > 0x7fffffffLL)
+    return HTSMSG_ERR_CONVERSION_IMPOSSIBLE;
+
+  *s32p = s64;
+  return 0;
+}
 
 /*
  *
index f619323bf7ea0914ca7ff658e80dc9f4f3ca1989..e759bcef40b5bde99fca101942a7e4e24d56f7fe 100644 (file)
@@ -276,6 +276,8 @@ int htsmsg_field_get_u32(htsmsg_field_t *f, uint32_t *u32p);
  */
 int htsmsg_get_s32(htsmsg_t *msg, const char *name,  int32_t *s32p);
 
+int htsmsg_field_get_s32(htsmsg_field_t *f, int32_t *s32p);
+
 /**
  * Get an integer as an signed 64 bit integer.
  *