]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
mpegts network: create network bouquet for all mpegts networks, fixes #4366
authorJaroslav Kysela <perex@perex.cz>
Fri, 12 May 2017 14:31:52 +0000 (16:31 +0200)
committerJaroslav Kysela <perex@perex.cz>
Fri, 12 May 2017 14:32:17 +0000 (16:32 +0200)
12 files changed:
src/bouquet.c
src/epggrab/module/opentv.c
src/input/mpegts.h
src/input/mpegts/dvb_psi.c
src/input/mpegts/iptv/iptv.c
src/input/mpegts/iptv/iptv_auto.c
src/input/mpegts/iptv/iptv_mux.c
src/input/mpegts/iptv/iptv_private.h
src/input/mpegts/iptv/iptv_service.c
src/input/mpegts/mpegts_network.c
src/input/mpegts/mpegts_service.c
src/subscriptions.c

index c6eb56bd504b9b25ed9ff1d86eb1c32a86aea918..9e63a34f43af8451bb7f58a5380ca2f659093f13 100644 (file)
@@ -24,6 +24,7 @@
 #include "channels.h"
 #include "service_mapper.h"
 #include "download.h"
+#include "input.h"
 
 typedef struct bouquet_download {
   bouquet_t  *bq;
@@ -599,13 +600,23 @@ void
 bouquet_scan ( bouquet_t *bq )
 {
   void mpegts_mux_bouquet_rescan ( const char *src, const char *extra );
-  void iptv_bouquet_trigger_by_uuid( const char *uuid );
+  char *mpegts_network_uuid = NULL;
+  if (bq->bq_src) {
 #if ENABLE_IPTV
-  if (bq->bq_src && strncmp(bq->bq_src, "iptv-network://", 15) == 0)
-    return iptv_bouquet_trigger_by_uuid(bq->bq_src + 15);
+    if (strncmp(bq->bq_src, "iptv-network://", 15) == 0)
+      mpegts_network_uuid = bq->bq_src + 15;
 #endif
-  if (bq->bq_src && strncmp(bq->bq_src, "exturl://", 9) == 0)
-    return bouquet_download_trigger(bq);
+    if (strncmp(bq->bq_src, "mpegts-network://", 17) == 0)
+      mpegts_network_uuid = bq->bq_src + 17;
+    else if (strncmp(bq->bq_src, "exturl://", 9) == 0)
+      return bouquet_download_trigger(bq);
+
+    if (mpegts_network_uuid) {
+      mpegts_network_t *mn = mpegts_network_find(mpegts_network_uuid);
+      if (mn)
+        return mpegts_network_bouquet_trigger(mn, 0);
+    }
+  }
   mpegts_mux_bouquet_rescan(bq->bq_src, bq->bq_comment);
   bq->bq_rescan = 0;
 }
index 6abf06f511154720756634a1f9d80a175097739d..8674bae23ce13321be72f73658dd8bebb550b6a3 100644 (file)
@@ -541,6 +541,7 @@ opentv_desc_channels
       tvhtrace(LS_OPENTV, "%s:      cnum changed (%i != %i)", mt->mt_name, cnum, (int)svc->s_dvb_opentv_chnum);
       svc->s_dvb_opentv_chnum = cnum;
       svc->s_dvb_opentv_id = unk;
+      mpegts_network_bouquet_trigger(mm->mm_network, 0);
       service_request_save((service_t *)svc, 0);
     }
 skip_chnum:
index 6d0158510af4880153c611a7b7c68e2ad1c04303..f3fa5858adccd282e750203380f4d91e1b9d3b66 100644 (file)
@@ -330,12 +330,15 @@ struct mpegts_network
   mpegts_mux_queue_t mn_scan_pend;    // Pending muxes
   mpegts_mux_queue_t mn_scan_active;  // Active muxes
   mtimer_t           mn_scan_timer;   // Timer for activity
+  mtimer_t           mn_bouquet_timer;
 
   /*
    * Functions
    */
   void              (*mn_delete)       (mpegts_network_t*, int delconf);
   void              (*mn_display_name) (mpegts_network_t*, char *buf, size_t len);
+  int               (*mn_bouquet_source) (mpegts_network_t*, char *buf, size_t len);
+  int               (*mn_bouquet_comment) (mpegts_network_t*, char *buf, size_t len);
   htsmsg_t *        (*mn_config_save)  (mpegts_network_t*, char *filename, size_t fsize);
   mpegts_mux_t*     (*mn_create_mux)
     (mpegts_network_t*, void *origin, uint16_t onid, uint16_t tsid,
@@ -352,6 +355,7 @@ struct mpegts_network
   uint16_t mn_satip_source;
   int      mn_autodiscovery;
   int      mn_skipinitscan;
+  int      mn_bouquet;
   char    *mn_charset;
   int      mn_idlescan;
   int      mn_ignore_chnum;
@@ -866,6 +870,10 @@ int mpegts_network_set_network_name ( mpegts_network_t *mn, const char *name );
 void mpegts_network_scan ( mpegts_network_t *mn );
 void mpegts_network_get_type_str( mpegts_network_t *mn, char *buf, size_t buflen );
 
+void mpegts_network_bouquet_trigger0(mpegts_network_t *mn, int timeout);
+static inline void mpegts_network_bouquet_trigger(mpegts_network_t *mn, int timeout)
+{ if (mn->mn_bouquet) mpegts_network_bouquet_trigger0(mn, timeout); }
+
 htsmsg_t * mpegts_network_wizard_get ( mpegts_input_t *mi, const idclass_t *idc,
                                        mpegts_network_t *mn, const char *lang );
 void mpegts_network_wizard_create ( const char *clazz, htsmsg_t **nlist, const char *lang );
index d01fb944a639a8b39054f951df49f258b714279c..6deb1761eac895974436a9efcfda596099d8bfa3 100644 (file)
@@ -481,7 +481,7 @@ dvb_desc_service_list
 
 static int
 dvb_desc_local_channel
-  ( mpegts_table_t *mt, const uint8_t *ptr, int len,
+  ( mpegts_table_t *mt, mpegts_network_t *mn, const uint8_t *ptr, int len,
     uint8_t dtag, mpegts_mux_t *mm, dvb_bat_id_t *bi, int prefer )
 {
   int save = 0;
@@ -505,6 +505,7 @@ dvb_desc_local_channel
                     s->s_dvb_channel_num != lcn) {
           s->s_dvb_channel_dtag = dtag;
           s->s_dvb_channel_num = lcn;
+          mpegts_network_bouquet_trigger(mn, 0);
           idnode_changed(&s->s_id);
           service_refresh_channel((service_t*)s);
         }
@@ -1192,12 +1193,14 @@ dvb_nit_mux
   int dllen, dlen;
   const uint8_t *dlptr, *dptr, *lptr_orig = lptr;
   const char *charset;
+  mpegts_network_t *mn;
   char buf[128], dauth[256];
 
   if (mux && mux->mm_enabled != MM_ENABLE)
     bi = NULL;
 
-  charset = dvb_charset_find(mux ? mux->mm_network : mm->mm_network, mux, NULL);
+  mn = mux ? mux->mm_network : mm->mm_network;
+  charset = dvb_charset_find(mn, mux, NULL);
 
   if (mux)
     mpegts_mux_nice_name(mux, buf, sizeof(buf));
@@ -1297,7 +1300,7 @@ dvb_nit_mux
     case 0x88:
       if (priv == 0x28) {
         /* HD simulcast */
-        if (dvb_desc_local_channel(mt, dptr, dlen, dtag, mux, bi, 1))
+        if (dvb_desc_local_channel(mt, mn, dptr, dlen, dtag, mux, bi, 1))
           return -1;
       }
       break;
@@ -1305,7 +1308,7 @@ dvb_nit_mux
       if (priv == 0 || priv == 0x362275)
       /* fall thru */
 lcn:
-      if (dvb_desc_local_channel(mt, dptr, dlen, dtag, mux, bi, 0))
+      if (dvb_desc_local_channel(mt, mn, dptr, dlen, dtag, mux, bi, 0))
         return -1;
       break;
     case DVB_DESC_FREESAT_LCN:
@@ -1809,6 +1812,7 @@ atsc_vct_callback
           save = 1;
         }
         if (s->s_dvb_channel_num != maj || s->s_dvb_channel_minor != min) {
+          mpegts_network_bouquet_trigger(mn, 0);
           s->s_dvb_channel_num = maj;
           s->s_dvb_channel_minor = min;
           save = 1;
index 7d822042d17bffbf3ad3c56ce6b1a0432a74efda..597c40d0c7c7014d7d02229eefdc16022b1079d5 100644 (file)
@@ -23,7 +23,6 @@
 #include "settings.h"
 #include "htsstr.h"
 #include "channels.h"
-#include "bouquet.h"
 #include "packet.h"
 
 #include <sys/socket.h>
@@ -83,51 +82,6 @@ iptv_handler_find ( const char *scheme )
   return RB_FIND(&iptv_handlers, &ih, link, ih_cmp);
 }
 
-/* **************************************************************************
- * IPTV bouquet
- * *************************************************************************/
-
-static bouquet_t *
-iptv_bouquet_get (iptv_network_t *in, int create)
-{
-  char buf[128], ubuf[UUID_HEX_SIZE];
-  snprintf(buf, sizeof(buf), "iptv-network://%s", idnode_uuid_as_str(&in->mn_id, ubuf));
-  return bouquet_find_by_source(in->mn_network_name, buf, create);
-}
-
-static void
-iptv_bouquet_update(void *aux)
-{
-  iptv_network_t *in = aux;
-  mpegts_mux_t *mm;
-  mpegts_service_t *ms;
-  bouquet_t *bq = in->in_bouquet ? iptv_bouquet_get(in, 1) : NULL;
-  uint32_t seen = 0;
-  if (bq == NULL)
-    return;
-  bouquet_change_comment(bq, in->in_url, 1);
-  LIST_FOREACH(mm, &in->mn_muxes, mm_network_link)
-    LIST_FOREACH(ms, &mm->mm_services, s_dvb_mux_link) {
-      bouquet_add_service(bq, (service_t *)ms, ((iptv_mux_t *)mm)->mm_iptv_chnum, NULL);
-      seen++;
-    }
-  bouquet_completed(bq, seen);
-}
-
-void
-iptv_bouquet_trigger(iptv_network_t *in, int timeout)
-{
-  mtimer_arm_rel(&in->in_bouquet_timer, iptv_bouquet_update, in, sec2mono(timeout));
-}
-
-void
-iptv_bouquet_trigger_by_uuid(const char *uuid)
-{
-  iptv_network_t *in = (iptv_network_t *)idnode_find(uuid, &iptv_network_class, NULL);
-  iptv_bouquet_trigger(in, 0);
-}
-
-
 /* **************************************************************************
  * IPTV input
  * *************************************************************************/
@@ -672,6 +626,25 @@ iptv_input_mux_started ( iptv_mux_t *im )
                        im->mm_iptv_atsc ? DVB_SYS_ATSC_ALL : DVB_SYS_DVBT);
 }
 
+static int
+iptv_network_bouquet_source (mpegts_network_t *mn, char *source, size_t len)
+{
+  iptv_network_t *in = (mpegts_network_t *)mn;
+  char ubuf[UUID_HEX_SIZE];
+  snprintf(source, len, "iptv-network://%s", idnode_uuid_as_str(&in->mn_id, ubuf));
+  return 0;
+}
+
+static int
+iptv_network_bouquet_comment (mpegts_network_t *mn, char *comment, size_t len)
+{
+  iptv_network_t *in = (mpegts_network_t *)mn;
+  if (in->in_url == NULL || in->in_url[0] == '\0')
+    return -1;
+  snprintf(comment, len, "%s", in->in_url);
+  return 0;
+}
+
 static void
 iptv_network_delete ( mpegts_network_t *mn, int delconf )
 {
@@ -684,17 +657,13 @@ iptv_network_delete ( mpegts_network_t *mn, int delconf )
 
   idnode_save_check(&mn->mn_id, delconf);
 
-  mtimer_disarm(&in->in_bouquet_timer);
-
   if (in->mn_id.in_class == &iptv_auto_network_class)
     iptv_auto_network_done(in);
 
   /* Remove config */
-  if (delconf) {
+  if (delconf)
     hts_settings_remove("input/iptv/networks/%s",
                         idnode_uuid_as_str(&in->mn_id, ubuf));
-    bouquet_delete(iptv_bouquet_get(in, 0));
-  }
 
   /* delete */
   free(in->in_remove_args);
@@ -844,22 +813,6 @@ iptv_auto_network_class_notify_url( void *in, const char *lang )
   iptv_auto_network_trigger(in);
 }
 
-static void
-iptv_auto_network_class_notify_bouquet( void *in, const char *lang )
-{
-  iptv_network_t *mn = in;
-  bouquet_t *bq;
-  if (mn->in_bouquet) {
-    iptv_bouquet_trigger(mn, 0);
-  } else {
-    if (mn->in_bouquet) {
-      bq = iptv_bouquet_get(mn, 0);
-      if (bq)
-        bouquet_delete(bq);
-    }
-  }
-}
-
 static htsmsg_t *
 iptv_auto_network_class_charset_list(void *o, const char *lang)
 {
@@ -884,14 +837,6 @@ const idclass_t iptv_auto_network_class = {
       .notify   = iptv_auto_network_class_notify_url,
       .opts     = PO_MULTILINE
     },
-    {
-      .type     = PT_BOOL,
-      .id       = "bouquet",
-      .name     = N_("Create bouquet"),
-      .desc     = N_("Create a bouquet from the playlist."),
-      .off      = offsetof(iptv_network_t, in_bouquet),
-      .notify   = iptv_auto_network_class_notify_bouquet,
-    },
     {
       .type     = PT_STR,
       .id       = "ctx_charset",
@@ -999,6 +944,8 @@ iptv_network_create0
     free(in);
     return NULL;
   }
+  in->mn_bouquet_source = iptv_network_bouquet_source;
+  in->mn_bouquet_comment= iptv_network_bouquet_comment;
   in->mn_delete         = iptv_network_delete;
   in->mn_create_service = iptv_network_create_service;
   in->mn_mux_class      = iptv_network_mux_class;
index f17ca0a3d6b477cfd001d57a5d84103401f45e3f..74607f6d8f47c4fc55cb8c681ee685cc8c0b5bed 100644 (file)
@@ -215,7 +215,7 @@ skip_url:
         change = 1;
       }
       if (im->mm_iptv_chnum != chnum) {
-        iptv_bouquet_trigger(in, 0); /* propagate LCN change */
+        mpegts_network_bouquet_trigger((mpegts_network_t *)in, 0); /* propagate LCN change */
         im->mm_iptv_chnum = chnum;
         change = 1;
       }
index eadbe613325d8958d43b5b5a59d501bf617df93d..10f474b99cba888c95f455aeec805702a8657efc 100644 (file)
@@ -373,7 +373,7 @@ iptv_mux_create0 ( iptv_network_t *in, const char *uuid, htsmsg_t *conf )
     ms->s_pmt_pid = SERVICE_PMT_AUTO;
     htsmsg_destroy(conf);
     if (ms)
-      iptv_bouquet_trigger(in, 0);
+      mpegts_network_bouquet_trigger((mpegts_network_t *)in, 0);
   }
   htsmsg_destroy(c2);
 
index c13bf9052fbddaac28f2357c922b3dac30dc22af..3b108bacc0eb16061ded2f03b325fdceb6924399 100644 (file)
@@ -36,8 +36,6 @@
 #define IPTV_KILL_USR1   4
 #define IPTV_KILL_USR2   5
 
-struct bouquet;
-
 extern pthread_mutex_t iptv_lock;
 
 typedef struct iptv_input   iptv_input_t;
@@ -93,8 +91,6 @@ struct iptv_network
 
   char    *in_url;
   char    *in_url_sane;
-  int      in_bouquet;
-  mtimer_t in_bouquet_timer;
   char    *in_ctx_charset;
   int64_t  in_channel_number;
   uint32_t in_refetch_period;
@@ -182,7 +178,6 @@ extern iptv_input_t   *iptv_input;
 extern iptv_network_t *iptv_network;
 
 
-void iptv_bouquet_trigger(iptv_network_t *in, int timeout);
 int iptv_url_set ( char **url, char **sane_url, const char *str, int allow_file, int allow_pipe );
 
 void iptv_mux_load_all ( void );
index 554e35b71186682bdd307c59a3aa2da0febff36d..8cf9e43898dd3d29e947a6a7d68435924cfd9c68 100644 (file)
@@ -119,7 +119,6 @@ iptv_service_create0
   ( iptv_mux_t *im, uint16_t sid, uint16_t pmt,
     const char *uuid, htsmsg_t *conf )
 {
-  iptv_network_t *in = (iptv_network_t *)im->mm_network;
   iptv_service_t *is = (iptv_service_t*)
     mpegts_service_create0(calloc(1, sizeof(mpegts_service_t)),
                            &mpegts_service_class, uuid,
@@ -138,8 +137,5 @@ iptv_service_create0
     if (im->mm_iptv_svcname)
       is->s_dvb_svcname = strdup(im->mm_iptv_svcname);
 
-  if (in->in_bouquet)
-    iptv_bouquet_trigger(in, 1);
-
   return is;
 }
index ec0a949d37a70780163c1890bffe6e9d1d19fb23..161ccdb93f009dc6263b7710fdacda73cec3218e 100644 (file)
 #include "channels.h"
 #include "access.h"
 #include "dvb_charset.h"
+#include "bouquet.h"
 
 #include <assert.h>
 
+static bouquet_t * mpegts_network_bouquet_get (mpegts_network_t *, int);
+
 /* ****************************************************************************
  * Class definition
  * ***************************************************************************/
@@ -140,6 +143,20 @@ mpegts_network_discovery_enum ( void *o, const char *lang )
   return strtab2htsmsg(tab, 1, lang);
 }
 
+static void
+mpegts_network_class_notify_bouquet( void *in, const char *lang )
+{
+  mpegts_network_t *mn = in;
+  bouquet_t *bq;
+  if (mn->mn_bouquet) {
+    mpegts_network_bouquet_trigger(mn, 0);
+  } else {
+    bq = mpegts_network_bouquet_get(mn, 0);
+    if (bq)
+      bouquet_delete(bq);
+  }
+}
+
 CLASS_DOC(mpegts_network)
 PROP_DOC(network_discovery)
 
@@ -189,6 +206,15 @@ const idclass_t mpegts_network_class =
       .opts     = PO_ADVANCED | PO_DOC_NLIST,
       .def.i    = MN_DISCOVERY_NEW
     },
+    {
+      .type     = PT_BOOL,
+      .id       = "bouquet",
+      .name     = N_("Create bouquet"),
+      .desc     = N_("Create a bouquet with all services in the network."),
+      .off      = offsetof(mpegts_network_t, mn_bouquet),
+      .notify   = mpegts_network_class_notify_bouquet,
+    },
+
     {
       .type     = PT_BOOL,
       .id       = "skipinitscan",
@@ -320,6 +346,65 @@ mpegts_network_display_name
   strncpy(buf, mn->mn_network_name ?: "unknown", len);
 }
 
+static bouquet_t *
+mpegts_network_bouquet_get (mpegts_network_t *mn, int create)
+{
+  char buf[128];
+  if (mn->mn_bouquet_source(mn, buf, sizeof(buf)))
+    return NULL;
+  return bouquet_find_by_source(mn->mn_network_name, buf, create);
+}
+
+static void
+mpegts_network_bouquet_update(void *aux)
+{
+  mpegts_network_t *mn = aux;
+  mpegts_mux_t *mm;
+  mpegts_service_t *ms;
+  int64_t chnum;
+  char buf[128];
+  uint32_t seen = 0;
+  bouquet_t *bq = mn->mn_bouquet ? mpegts_network_bouquet_get(mn, 1) : NULL;
+  if (bq == NULL)
+    return;
+  if (!mn->mn_bouquet_comment(mn, buf, sizeof(buf)))
+    bouquet_change_comment(bq, buf, 1);
+  LIST_FOREACH(mm, &mn->mn_muxes, mm_network_link)
+    LIST_FOREACH(ms, &mm->mm_services, s_dvb_mux_link) {
+      chnum = ms->s_channel_number((service_t *)ms);
+      bouquet_add_service(bq, (service_t *)ms, chnum, NULL);
+      seen++;
+    }
+  bouquet_completed(bq, seen);
+}
+
+void
+mpegts_network_bouquet_trigger0(mpegts_network_t *mn, int timeout)
+{
+  mtimer_arm_rel(&mn->mn_bouquet_timer, mpegts_network_bouquet_update,
+                 mn, sec2mono(timeout));
+}
+
+static int
+mpegts_network_bouquet_source
+  ( mpegts_network_t *mn, char *source, size_t len)
+{
+  char ubuf[UUID_HEX_SIZE];
+  snprintf(source, len, "mpegts-network://%s",
+           idnode_uuid_as_str(&mn->mn_id, ubuf));
+  return 0;
+}
+
+static int
+mpegts_network_bouquet_comment
+  ( mpegts_network_t *mn, char *comment, size_t len)
+{
+  if (!mn->mn_provider_network_name || mn->mn_provider_network_name[0] == '\0')
+    return -1;
+  snprintf(comment, len, "%s", mn->mn_provider_network_name);
+  return 0;
+}
+
 static htsmsg_t *
 mpegts_network_config_save
   ( mpegts_network_t *mn, char *filename, size_t size )
@@ -376,6 +461,11 @@ mpegts_network_delete
 
   idnode_save_check(&mn->mn_id, delconf);
 
+  /* Bouquet */
+  mtimer_disarm(&mn->mn_bouquet_timer);
+  if (delconf)
+    bouquet_delete(mpegts_network_bouquet_get(mn, 0));
+
   /* Remove from global list */
   LIST_REMOVE(mn, mn_global_link);
 
@@ -422,6 +512,8 @@ mpegts_network_create0
 
   /* Default callbacks */
   mn->mn_display_name   = mpegts_network_display_name;
+  mn->mn_bouquet_source = mpegts_network_bouquet_source;
+  mn->mn_bouquet_comment= mpegts_network_bouquet_comment;
   mn->mn_config_save    = mpegts_network_config_save;
   mn->mn_create_mux     = mpegts_network_create_mux;
   mn->mn_create_service = mpegts_network_create_service;
index f4f9153b5547e1c558ffddf760d7c1234cdb0a5a..5f85327323c8c0d141cfa70c22f9a2065c8e49ad 100644 (file)
@@ -768,6 +768,7 @@ mpegts_service_create0
 {
   int r;
   char buf[256];
+  mpegts_network_t *mn = mm->mm_network;
   time_t dispatch_clock = gclk();
 
   /* defaults for older version */
@@ -817,6 +818,9 @@ mpegts_service_create0
   mpegts_mux_nice_name(mm, buf, sizeof(buf));
   tvhdebug(LS_MPEGTS, "%s - add service %04X %s", buf, s->s_dvb_service_id, s->s_dvb_svcname);
 
+  /* Bouquet */
+  mpegts_network_bouquet_trigger(mn, 1);
+
   /* Notification */
   idnode_notify_changed(&mm->mm_id);
   idnode_notify_changed(&mm->mm_network->mn_id);
index a54a69217a885c3f29b2b5bdaa9e836630b1add1..e4e3037a7068164254b0dee2e53be89e8ce16a5f 100644 (file)
@@ -936,7 +936,6 @@ subscription_create_from_service(profile_chain_t *prch,
  *
  */
 #if ENABLE_MPEGTS
-#include "input/mpegts.h"
 th_subscription_t *
 subscription_create_from_mux(profile_chain_t *prch,
                              tvh_input_t *ti,