From: E.Smith <31170571+azlm8t@users.noreply.github.com> Date: Tue, 5 Sep 2017 11:43:19 +0000 (+0100) Subject: eit: Extract season/episode numbers from OTA EIT. (#4287). X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=3673e974a983475daff844f6484a7a203676534b;p=thirdparty%2Ftvheadend.git eit: Extract season/episode numbers from OTA EIT. (#4287). Broadcasters often include season and episode number in the summary text in the OTA EIT. For example, UK broadcasters often, but not always, have a description of "Lorem ipsum (S5 Ep 8)" or "Lorem ipsum (S3 Ep 4/9)" or "Lorem ipsum (Ep 4)". From this we can use a regular expression match to extract the season and episode data on a best effort basis. This logic is based on the opentv extractor. This is done via config files that are named after the grabber module and exist in this directory: data/conf/epggrab/eit/fixup/ Example names would be uk_freeview. If the module-specific config file does not exist then we fallback to trying the first component of the filename. In the above example that would be "uk". This avoids having duplicate files in the case where we have DVB-S and DVB-T in the same country that share the same extraction regex. The configuration file should contain season_num and episode_num sections that can contain multiple regular expressions to apply in sequence until one produces a match. For DVB-S, the configuration file normally needs to be copied to a file named "eit" since data is broadcast via that mechanism. This isn't done by default since the eit grabber is used by multiple countries that may use different regular expressions. Issue: #4287 --- diff --git a/data/conf/epggrab/eit/fixup/uk b/data/conf/epggrab/eit/fixup/uk new file mode 100644 index 000000000..b149472da --- /dev/null +++ b/data/conf/epggrab/eit/fixup/uk @@ -0,0 +1,17 @@ +{ + "season_num": [ + " *\\(S ?([0-9]+),? [Ee]p? ?[0-9]+\\)", + " *\\(S ?([0-9]+),? [Ee]p? ?[0-9]+/[0-9]+\\)", + " S ?([0-9]+)[ /][Ee]p? ?[0-9]+", + "^S ?([0-9]+),? [Ee]p? ?[0-9]+\\\." + ], + "episode_num": [ + " *\\(S ?[0-9]+,? [Ee]p? ?([0-9]+)\\)", + " *\\(S ?[0-9]+,? [Ee]p? ?([0-9]+)/[0-9]+\\)", + " S ?[0-9]+[ /][Ee]p? ?([0-9]+)", + "^S ?[0-9]+,? [Ee]p? ?([0-9]+)\\\.", + " *\\([Ee]p ?([0-9]+)\\)", + " *\\([Ee]p ?([0-9]+)/[0-9]+\\)", + "^([0-9]+)/[0-9]+\. " + ] +} diff --git a/src/epggrab/module/eit.c b/src/epggrab/module/eit.c index e41aaba1d..8fc8fafe7 100644 --- a/src/epggrab/module/eit.c +++ b/src/epggrab/module/eit.c @@ -24,6 +24,7 @@ #include "epg.h" #include "epggrab.h" #include "epggrab/private.h" +#include "eitpatternlist.h" #include "input.h" #include "input/mpegts/dvb_charset.h" #include "dvr/dvr.h" @@ -44,6 +45,15 @@ typedef struct eit_private #define EIT_SPEC_UK_FREESAT 1 #define EIT_SPEC_NZ_FREEVIEW 2 + +/* Provider configuration */ +typedef struct eit_module_t +{ + epggrab_module_ota_t ; ///< Base struct + eit_pattern_list_t p_snum; + eit_pattern_list_t p_enum; +} eit_module_t; + /* ************************************************************************ * Status handling * ***********************************************************************/ @@ -421,6 +431,7 @@ static int _eit_process_event_one const uint8_t *ptr, int len, int local, int *resched, int *save ) { + eit_module_t* eit_mod = (eit_module_t*)mod; int dllen, save2 = 0, rsonly = 0; time_t start, stop; uint16_t eid; @@ -580,6 +591,22 @@ static int _eit_process_event_one ee = epg_episode_find_by_broadcast(ebc, mod, 1, save, &changes4); } + epg_episode_num_t en; + memset(&en, 0, sizeof(en)); + + if (ev.summary) { + /* search for season number */ + char buffer[2048]; + const char* summary = lang_str_get(ev.summary, ev.default_charset); + if (eit_pattern_apply_list(buffer, sizeof(buffer), summary, &eit_mod->p_snum)) + if ((en.s_num = atoi(buffer))) + tvhtrace(LS_TBL_EIT," extract season number %d using %s", en.s_num, mod->id); + /* ...for episode number */ + if (eit_pattern_apply_list(buffer, sizeof(buffer), summary, &eit_mod->p_enum)) + if ((en.e_num = atoi(buffer))) + tvhtrace(LS_TBL_EIT," extract episode number %d using %s", en.e_num, mod->id); + } + /* Update Episode */ if (ee) { *save |= epg_broadcast_set_episode(ebc, ee, &changes2); @@ -596,6 +623,9 @@ static int _eit_process_event_one if (ev.extra) *save |= epg_episode_set_extra(ee, extra, &changes4); #endif + /* save any found episode number */ + if (en.s_num || en.e_num || en.p_num) + *save |= epg_episode_set_epnum(ee, &en, &changes4); *save |= epg_episode_change_finish(ee, changes4, 0); } @@ -899,6 +929,66 @@ static int _eit_tune return r; } +static int _eit_fixup_load_one ( htsmsg_t *m, eit_module_t* mod ) +{ + eit_pattern_compile_list(&mod->p_snum, htsmsg_get_list(m, "season_num")); + eit_pattern_compile_list(&mod->p_enum, htsmsg_get_list(m, "episode_num")); + return 1; +} + +static eit_module_t *eit_module_ota_create + ( const char *id, int subsys, const char *saveid, + const char *name, int priority, + epggrab_ota_module_ops_t *ops ) +{ + eit_module_t * mod = (eit_module_t *) + epggrab_module_ota_create(calloc(1, sizeof(eit_module_t)), + id, subsys, saveid, + name, priority, ops); + + const char config_path[] = "epggrab/eit/fixup/%s"; + const char *config_file = id; + + /* Attempt to load config file based on grabber id such as + * uk_freeview. + */ + htsmsg_t *m = hts_settings_load(config_path, config_file); + char *generic_name = NULL; + if (!m) { + /* No config file so try loading a generic config based on + * the first component of the id. In the above case it would + * be "uk". This allows config for a country to be shared across + * two grabbers such as DVB-T and DVB-S. + */ + generic_name = strdup(id); + if (generic_name) { + char *underscore = strstr(generic_name, "_"); + if (underscore) { + /* Terminate the string at the underscore */ + *underscore = 0; + config_file = generic_name; + m = hts_settings_load(config_path, config_file); + } + } + } + + if (m) { + const int r = _eit_fixup_load_one(m, mod); + if (r > 0) + tvhinfo(LS_TBL_EIT, "fixup %s loaded %s", id, config_file); + else + tvhwarn(LS_TBL_EIT, "fixup %s failed", id); + htsmsg_destroy(m); + } else { + tvhinfo(LS_TBL_EIT, "no fixup config files loaded for %s", id); + } + + if (generic_name) + free(generic_name); + + return mod; +} + #define EIT_OPS(name, _pid, _conv, _spec) \ static eit_private_t opaque_##name = { \ .pid = (_pid), \ @@ -912,7 +1002,7 @@ static int _eit_tune } #define EIT_CREATE(id, name, prio, ops) \ - epggrab_module_ota_create(NULL, id, LS_TBL_EIT, NULL, name, prio, ops) + eit_module_ota_create(id, LS_TBL_EIT, NULL, name, prio, ops) void eit_init ( void ) {