]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
Add Sub-Title Processing Options for DVB OTA EPG
authorDeltaMikeCharlie <127641886+DeltaMikeCharlie@users.noreply.github.com>
Mon, 19 May 2025 19:45:04 +0000 (05:45 +1000)
committerFlole <Flole998@users.noreply.github.com>
Mon, 19 May 2025 22:26:01 +0000 (00:26 +0200)
src/epggrab/module/eit.c
src/input/mpegts.h
src/input/mpegts/mpegts_service.c

index 1b40b1dc3ba4c5e8c76784f8b2f957d5ae77ad26..3ff84ee26c2173bf60080a7210c89fbb029273ee 100644 (file)
@@ -693,6 +693,10 @@ static int _eit_process_event_one
   char tm1[32], tm2[32];
   int short_target = ((eit_module_t *)mod)->short_target;
 
+  lang_str_t *temp_string;        //}
+  lang_str_ele_t *temp_ele;       //} Used for appending/prepending to the desc.
+  const char *temp_s1, *temp_s2;  //}
+
   /* Core fields */
   eid   = ptr[0] << 8 | ptr[1];
   start = dvb_convert_date(&ptr[2], local);
@@ -791,8 +795,160 @@ static int _eit_process_event_one
     *save |= epg_broadcast_set_rating_label(ebc, ev->rating_label, &changes);
     }
 
+  /*
+      Notes on EPG fields. DMC, May 2025.
+
+      ev->title :   Originates from EIT tag 0x4d 'short_event_descriptor' 'event name'
+      ev->summary : Originates from EIT tag 0x4d 'short_event_descriptor' 'text describing the event'
+      ev->desc :    Originates from EIT tag 0c4e 'extended_event_descriptor'
+      ev-subtitle : Originates from scraping operations performed by previous functions.
+
+      If the grabber scraping option is enabled:
+      ev->title, ev->subtitle, ev->summary may be set/update/replaced by scraped values.
+
+      Eventually, if the sub-title is empty, the summary will be used in its place.
+
+      Summary of possible EPG Text manipulation operations.
+
+      Defined in EIT EPG Grabber
+      'Set the short EPG description to given target'
+      short_target: *0 = Subtitle* | 1 = Summary | 2 = Subtitle and summary
+
+      (New features from here..)
+      Defined in MPGTS Service
+      svc->s_dvb_subtitle_processing
+      [*None* | Save in Description | Append to Description | Prepend to Description]
+      This is only active if short_target == 0 so that the EPG grabber setting
+      takes priority over the service setting.
+      
+      svc->s_dvb_ignore_matching_subtitle [True | *False*]
+      If the Sub-title and the Title contain identical content, ignore the Sub-title and only save the Title.
+   */
+
+  //If processing is enabled AND the grabber is saving the sub-title in the sub-title then
+  //save the sub-title in the description provided that the description is also empty OR
+  //append/prepend the sub-title to the description if the description is not empty.
+  if ((svc->s_dvb_subtitle_processing != SVC_PROCESS_SUBTITLE_NONE) && (ev->summary || ev->subtitle) && short_target == 0)
+  {
+      //If there is not already a description, just use the subtitle/summary instead
+      if(!ev->desc)
+      {
+        //If there was a sub-title scraped, use that.
+        if (ev->subtitle)
+        {
+          *save |= epg_broadcast_set_description(ebc, ev->subtitle, &changes);
+          lang_str_destroy(ev->subtitle);
+          ev->subtitle = lang_str_create();
+          tvhtrace(LS_TBL_EIT, "Description set to sub-title.");
+        }
+        else
+        {
+          *save |= epg_broadcast_set_description(ebc, ev->summary, &changes);
+          lang_str_destroy(ev->summary);
+          ev->summary = lang_str_create();
+          tvhtrace(LS_TBL_EIT, "Description set to summary.");
+        }
+      }
+      else //There is a description present so append/prepend as required.
+      {
+        temp_string = lang_str_create();
+        if(svc->s_dvb_subtitle_processing == SVC_PROCESS_SUBTITLE_APPEND)
+        {
+          if(ev->subtitle)
+          {
+            RB_FOREACH(temp_ele, ev->subtitle, link) {
+              temp_s1 = lang_str_get(ev->desc, temp_ele->lang);
+              lang_str_append(temp_string, temp_s1, temp_ele->lang);
+              lang_str_append(temp_string, " ", temp_ele->lang);
+              temp_s2 = lang_str_get(ev->subtitle, temp_ele->lang);
+              lang_str_append(temp_string, temp_s2, temp_ele->lang);
+              tvhtrace(LS_TBL_EIT, "Sub-title appended to description.");
+            }
+          }
+          else if(ev->summary)
+          {
+            RB_FOREACH(temp_ele, ev->summary, link) {
+              temp_s1 = lang_str_get(ev->desc, temp_ele->lang);
+              lang_str_append(temp_string, temp_s1, temp_ele->lang);
+              lang_str_append(temp_string, " ", temp_ele->lang);
+              temp_s2 = lang_str_get(ev->summary, temp_ele->lang);
+              lang_str_append(temp_string, temp_s2, temp_ele->lang);
+              tvhtrace(LS_TBL_EIT, "Summary appended to description.");
+            }
+          }
+        }//END Append
+
+        if(svc->s_dvb_subtitle_processing == SVC_PROCESS_SUBTITLE_PREPEND)
+        {
+          if(ev->subtitle)
+          {
+            RB_FOREACH(temp_ele, ev->subtitle, link) {
+              temp_s1 = lang_str_get(ev->subtitle, temp_ele->lang);
+              lang_str_append(temp_string, temp_s1, temp_ele->lang);
+              lang_str_append(temp_string, " ", temp_ele->lang);
+              temp_s2 = lang_str_get(ev->desc, temp_ele->lang);
+              lang_str_append(temp_string, temp_s2, temp_ele->lang);
+              tvhtrace(LS_TBL_EIT, "Sub-title prepended to description.");
+            }
+          }
+          else if(ev->summary)
+          {
+            RB_FOREACH(temp_ele, ev->summary, link) {
+              temp_s1 = lang_str_get(ev->summary, temp_ele->lang);
+              lang_str_append(temp_string, temp_s1, temp_ele->lang);
+              lang_str_append(temp_string, " ", temp_ele->lang);
+              temp_s2 = lang_str_get(ev->desc, temp_ele->lang);
+              lang_str_append(temp_string, temp_s2, temp_ele->lang);
+              tvhtrace(LS_TBL_EIT, "Summary prepended to description.");
+            }
+          }
+        }//END Prepend
+
+        //Save the new desc with the appended/prepended content.
+        *save |= epg_broadcast_set_description(ebc, temp_string, &changes);
+
+        //Nuke the summary because it is now part of the desc.
+        if(ev->summary)
+        {
+          lang_str_destroy(ev->summary);
+          ev->summary = lang_str_create();
+        }
+
+        //Nuke the subtitle because it is now part of the desc.
+        if(ev->subtitle)
+        {
+          lang_str_destroy(ev->subtitle);
+          ev->subtitle = lang_str_create();
+        }
+
+        //Clean up the temp language string.
+        if (temp_string)    lang_str_destroy(temp_string);
+
+      }//END append or prepend
+  }//END DVB sub-title processing
+
+  //If processing is enabled, delete the summary/sub-title if it is the same as the title.
+  if (svc->s_dvb_ignore_matching_subtitle && (ev->summary || ev->subtitle))
+  {
+      if (lang_str_compare(ev->title, ev->summary) == 0)  //0 = no differences
+      {
+          lang_str_destroy(ev->summary);
+          ev->summary = lang_str_create();
+          tvhtrace(LS_TBL_EIT, "Deleting summary, same as title.");
+      }
+
+      if (lang_str_compare(ev->title, ev->subtitle) == 0)  //0 = no differences
+      {
+          lang_str_destroy(ev->subtitle);
+          ev->subtitle = lang_str_create();
+          tvhtrace(LS_TBL_EIT, "Deleting sub-title, same as title.");
+      }
+  }
+
+  //The sub-title is set by scraping it from the EIT short description (held in the summary).
   if (ev->subtitle)
     *save |= epg_broadcast_set_subtitle(ebc, ev->subtitle, &changes);
+    //short_target: 0 = Subtitle | 2 = Subtitle and summary
   else if ((short_target == 0 || short_target == 2) && ev->summary)
     *save |= epg_broadcast_set_subtitle(ebc, ev->summary, &changes);
 #if TODO_ADD_EXTRA
index 9c4c57b73beced8d8bcd3c02e71b95f63a285cee..0fb5b192279f0dceb963b26f9a21d91ba3e1a915 100644 (file)
@@ -545,6 +545,11 @@ struct mpegts_mux
 #define PREFCAPID_ON       1
 #define PREFCAPID_FORCE    2
 
+#define SVC_PROCESS_SUBTITLE_NONE     0
+#define SVC_PROCESS_SUBTITLE_DESC     1
+#define SVC_PROCESS_SUBTITLE_APPEND   2
+#define SVC_PROCESS_SUBTITLE_PREPEND  3
+
 /* Service */
 struct mpegts_service
 {
@@ -574,6 +579,8 @@ struct mpegts_service
   char    *s_dvb_cridauth;
   uint16_t s_dvb_servicetype;
   int      s_dvb_ignore_eit;
+  int      s_dvb_subtitle_processing;       //Various options for replacing/augmenting the desc from the sub-title
+  int      s_dvb_ignore_matching_subtitle;  //Ignore the sub-title if same as title
   char    *s_dvb_charset;
   uint16_t s_dvb_prefcapid;
   int      s_dvb_prefcapid_lock;
index 9114131b4f4adc75f95d2a7df3d63607650d97e2..12cae7283809c3056c78ac80f8b66d6c3ccfad6b 100644 (file)
@@ -82,6 +82,18 @@ mpegts_service_pref_capid_lock_list ( void *o, const char *lang )
    return strtab2htsmsg(tab, 1, lang);
 }
 
+static htsmsg_t *
+mpegts_service_subtitle_procesing ( void *o, const char *lang )
+{
+  static const struct strtab tab[] = {
+    { N_("None"),                         SVC_PROCESS_SUBTITLE_NONE    }, //No processing.
+    { N_("Save in Description"),          SVC_PROCESS_SUBTITLE_DESC    }, //Save the sub-title in the desc if desc is empty.
+    { N_("Append to Description"),        SVC_PROCESS_SUBTITLE_APPEND  }, //Append, but if the desc is empty, just replace.
+    { N_("Prepend to Description"),       SVC_PROCESS_SUBTITLE_PREPEND }, //Prepend, but if the desc is empty, just replace.
+  };
+   return strtab2htsmsg(tab, 1, lang);
+}
+
 CLASS_DOC(mpegts_service)
 
 const idclass_t mpegts_service_class =
@@ -199,6 +211,28 @@ const idclass_t mpegts_service_class =
       .off      = offsetof(mpegts_service_t, s_dvb_ignore_eit),
       .opts     = PO_EXPERT,
     },
+    {
+      .type     = PT_INT,
+      .id       = "dvb_subtitle_processing",
+      .name     = N_("DVB Sub-title Processing"),
+      .desc     = N_("Select action to be taken with the Sub-title "
+                     "provided by the broadcaster: None; Save in Description; "
+                     "Append to Description; Prepend to Description. "
+                     "If the Description is empty, save, "
+                     "append and prepend will replace the Description."),
+      .off      = offsetof(mpegts_service_t, s_dvb_subtitle_processing),
+      .opts     = PO_EXPERT | PO_DOC_NLIST,
+      .list     = mpegts_service_subtitle_procesing,
+    },
+    {
+      .type     = PT_BOOL,
+      .id       = "dvb_ignore_matching_subtitle",
+      .name     = N_("Skip Sub-title matches Title"),
+      .desc     = N_("If the Sub-title and the Title contain identical content, "
+                     "ignore the Sub-title and only save the Title."),
+      .off      = offsetof(mpegts_service_t, s_dvb_ignore_matching_subtitle),
+      .opts     = PO_EXPERT,
+    },
     {
       .type     = PT_STR,
       .id       = "charset",