]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
channel: add possibility to reuse EPG from another channel, fixes #3217
authorJaroslav Kysela <perex@perex.cz>
Wed, 28 Oct 2015 20:09:33 +0000 (21:09 +0100)
committerJaroslav Kysela <perex@perex.cz>
Wed, 28 Oct 2015 20:09:33 +0000 (21:09 +0100)
src/channels.c
src/channels.h
src/dvr/dvr_autorec.c
src/dvr/dvr_db.c
src/epg.c
src/htsp_server.c

index b1301f71a9da549add424677bf60603aea29aa8b..9bab7e121c5a904500c8a0e18bc2de1a092c78c6 100644 (file)
@@ -397,6 +397,14 @@ const idclass_t channel_class = {
       .list     = bouquet_class_get_list,
       .opts     = PO_RDONLY
     },
+    {
+      .type     = PT_STR,
+      .id       = "epg_parent",
+      .name     = N_("Reuse EPG from"),
+      .list     = channel_class_get_list,
+      .off      = offsetof(channel_t, ch_epg_parent),
+      .opts     = PO_ADVANCED
+    },
     {}
   }
 };
@@ -782,6 +790,18 @@ channel_create0
   return ch;
 }
 
+static void
+channel_epg_parent_unlink ( channel_t *ch )
+{
+  char uuid[UUID_HEX_SIZE];
+  idnode_uuid_as_str(&ch->ch_id, uuid);
+  RB_FOREACH(ch, &channels, ch_link)
+    if (ch->ch_epg_parent && !strcmp(ch->ch_epg_parent, uuid)) {
+      free(ch->ch_epg_parent);
+      ch->ch_epg_parent = NULL;
+    }
+}
+
 void
 channel_delete ( channel_t *ch, int delconf )
 {
@@ -815,6 +835,7 @@ channel_delete ( channel_t *ch, int delconf )
   /* EPG */
   epggrab_channel_rem(ch);
   epg_channel_unlink(ch);
+  channel_epg_parent_unlink(ch);
 
   /* HTSP */
   htsp_channel_delete(ch);
@@ -826,6 +847,7 @@ channel_delete ( channel_t *ch, int delconf )
   /* Free memory */
   RB_REMOVE(&channels, ch, ch_link);
   idnode_unlink(&ch->ch_id);
+  free(ch->ch_epg_parent);
   free(ch->ch_name);
   free(ch->ch_icon);
   free(ch);
index 7a8c75508caab5ae2347518504ce18f4a9b5697c..51ec77b5875beea8cfc1b4a865d816951f4be864 100644 (file)
@@ -61,6 +61,7 @@ typedef struct channel
   LIST_HEAD(, th_subscription) ch_subscriptions;
 
   /* EPG fields */
+  char                 *ch_epg_parent;
   epg_broadcast_tree_t  ch_epg_schedule;
   epg_broadcast_t      *ch_epg_now;
   epg_broadcast_t      *ch_epg_next;
@@ -68,7 +69,7 @@ typedef struct channel
   gtimer_t              ch_epg_timer_head;
   gtimer_t              ch_epg_timer_current;
 
-  int ch_epgauto;
+  int                   ch_epgauto;
   idnode_list_head_t    ch_epggrab;                /* 1 = epggrab channel, 2 = channel */
 
   /* DVR */
@@ -181,4 +182,20 @@ const char *channel_get_epgid ( channel_t *ch );
 
 #define channel_get_id(ch)    idnode_get_short_uuid((&(ch)->ch_id))
 
+static inline channel_t *channel_epg_parent(channel_t *ch)
+{
+  if (ch->ch_epg_parent != NULL)
+    return channel_find_by_uuid(ch->ch_epg_parent);
+  return NULL;
+}
+
+static inline epg_broadcast_tree_t *channel_epg_schedule(channel_t *ch)
+{
+  if (ch->ch_epg_parent != NULL) {
+    channel_t *ch2 = channel_find_by_uuid(ch->ch_epg_parent);
+    if (ch2) return &ch2->ch_epg_schedule;
+  }
+  return &ch->ch_epg_schedule;
+}
+
 #endif /* CHANNELS_H */
index 9be718798ea409cd838b9100f4677018e5e544c3..130ac9a934390c890fa83a8e8d19ab9dc8153b6f 100644 (file)
@@ -1266,7 +1266,7 @@ dvr_autorec_changed(dvr_autorec_entry_t *dae, int purge)
 
   CHANNEL_FOREACH(ch) {
     if (!ch->ch_enabled) continue;
-    RB_FOREACH(e, &ch->ch_epg_schedule, sched_link) {
+    RB_FOREACH(e, channel_epg_schedule(ch), sched_link) {
       if(autorec_cmp(dae, e)) {
         enabled = 1;
         if (disabled) {
index fc18735bc8f1f75577fa8b0d46582c4aaad7dcda..a4f1708482ea0ca7823670aa648404e14ae36406 100644 (file)
@@ -942,7 +942,7 @@ not_so_good:
 
   e = NULL;
   pre = (60 * dvr_entry_get_extra_time_pre(de)) - 30;
-  RB_FOREACH(ev, &de->de_channel->ch_epg_schedule, sched_link) {
+  RB_FOREACH(ev, channel_epg_schedule(de->de_channel), sched_link) {
     if (de->de_bcast == ev) continue;
     if (ev->start - pre < dispatch_clock) continue;
     if (dvr_entry_fuzzy_match(de, ev, 0, INT64_MAX))
@@ -1472,7 +1472,7 @@ dvr_event_replaced(epg_broadcast_t *e, epg_broadcast_t *new_e)
 
     /* Find match */
     } else {
-      RB_FOREACH(e, &e->channel->ch_epg_schedule, sched_link) {
+      RB_FOREACH(e, channel_epg_schedule(e->channel), sched_link) {
         if (dvr_entry_fuzzy_match(de, e, e->dvb_eid,
                                   de->de_config->dvr_update_window)) {
           tvhtrace("dvr",
index aae95c023b12b12146f1f9c6a7e7960604345218..01b6b35d41e3336da08546ddcce253a61afeb487 100644 (file)
--- a/src/epg.c
+++ b/src/epg.c
@@ -2389,7 +2389,7 @@ static void
 _eq_add_channel ( epg_query_t *eq, channel_t *ch )
 {
   epg_broadcast_t *ebc;
-  RB_FOREACH(ebc, &ch->ch_epg_schedule, sched_link) {
+  RB_FOREACH(ebc, channel_epg_schedule(ch), sched_link) {
     if (ebc->episode)
       _eq_add(eq, ebc);
   }
index 52bcf8446a155dc8805fc31b6963001d4e087a0f..17e9f634601db49638b538dd1c550dbc2eb9d7d7 100644 (file)
@@ -587,6 +587,7 @@ static htsmsg_t *
 htsp_build_channel(channel_t *ch, const char *method, htsp_connection_t *htsp)
 {
   idnode_list_mapping_t *ilm;
+  channel_t *src = channel_epg_parent(ch) ?: ch;
   channel_tag_t *ct;
   service_t *t;
   epg_broadcast_t *now, *next = NULL;
@@ -635,8 +636,8 @@ htsp_build_channel(channel_t *ch, const char *method, htsp_connection_t *htsp)
     }
   }
 
-  now  = ch->ch_epg_now;
-  next = ch->ch_epg_next;
+  now  = src->ch_epg_now;
+  next = src->ch_epg_next;
   htsmsg_add_u32(out, "eventId", now ? now->id : 0);
   htsmsg_add_u32(out, "nextEventId", next ? next->id : 0);
 
@@ -1197,7 +1198,7 @@ htsp_method_async(htsp_connection_t *htsp, htsmsg_t *in)
   if (epg) {
     CHANNEL_FOREACH(ch) {
       if (!htsp_user_access_channel(htsp, ch)) continue;
-      RB_FOREACH(ebc, &ch->ch_epg_schedule, sched_link) {
+      RB_FOREACH(ebc, channel_epg_schedule(ch), sched_link) {
         if (epgMaxTime && ebc->start > epgMaxTime) break;
         htsmsg_t *e = htsp_build_event(ebc, "eventAdd", lang, lastUpdate, htsp);
         if (e) htsp_send_message(htsp, e, NULL);
@@ -1285,6 +1286,7 @@ htsp_method_getEvents(htsp_connection_t *htsp, htsmsg_t *in)
 
   /* Use event as starting point */
   if (e || ch) {
+    ch = channel_epg_parent(ch) ?: ch;
     if (!e) e = ch->ch_epg_now ?: ch->ch_epg_next;
 
     /* Output */
@@ -1302,7 +1304,7 @@ htsp_method_getEvents(htsp_connection_t *htsp, htsmsg_t *in)
     events = htsmsg_create_list();
     CHANNEL_FOREACH(ch) {
       int num = numFollowing;
-      RB_FOREACH(e, &ch->ch_epg_schedule, sched_link) {
+      RB_FOREACH(e, channel_epg_schedule(ch), sched_link) {
         if (maxTime && e->start > maxTime) break;
         htsmsg_add_msg(events, NULL, htsp_build_event(e, NULL, lang, 0, htsp));
         if (num == 1) break;