]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
IPTV: Autonetwork - add linking to bouquets
authorJaroslav Kysela <perex@perex.cz>
Thu, 15 Oct 2015 20:17:49 +0000 (22:17 +0200)
committerJaroslav Kysela <perex@perex.cz>
Thu, 15 Oct 2015 20:17:49 +0000 (22:17 +0200)
src/bouquet.c
src/bouquet.h
src/input/mpegts/iptv/iptv.c
src/input/mpegts/iptv/iptv_auto.c
src/input/mpegts/iptv/iptv_private.h
src/input/mpegts/iptv/iptv_service.c

index 2f6f186ac1fe820877dc381c7f3efb63198873d7..c12fa210babb784335793262fbe44b5f1d07df69 100644 (file)
@@ -500,6 +500,25 @@ bouquet_get_tag_number(bouquet_t *bq, service_t *t)
   return 0;
 }
 
+/**
+ *
+ */
+void
+bouquet_delete(bouquet_t *bq)
+{
+  if (bq == NULL) return;
+  bq->bq_enabled = 0;
+  bouquet_map_to_channels(bq);
+  if (!bq->bq_shield) {
+    hts_settings_remove("bouquet/%s", idnode_uuid_as_sstr(&bq->bq_id));
+    bouquet_destroy(bq);
+  } else {
+    idnode_set_free(bq->bq_services);
+    bq->bq_services = idnode_set_create(1);
+    bouquet_save(bq, 1);
+  }
+}
+
 /**
  *
  */
@@ -530,18 +549,7 @@ bouquet_class_save(idnode_t *self)
 static void
 bouquet_class_delete(idnode_t *self)
 {
-  bouquet_t *bq = (bouquet_t *)self;
-
-  bq->bq_enabled = 0;
-  bouquet_map_to_channels(bq);
-  if (!bq->bq_shield) {
-    hts_settings_remove("bouquet/%s", idnode_uuid_as_sstr(&bq->bq_id));
-    bouquet_destroy(bq);
-  } else {
-    idnode_set_free(bq->bq_services);
-    bq->bq_services = idnode_set_create(1);
-    bouquet_save(bq, 1);
-  }
+  bouquet_delete((bouquet_t *)self);
 }
 
 static const char *
index 351f9a23e912f38f84dc222b52bbeada67d876aa..4df82e76c97c54bc33031f0460296517b0b74b5f 100644 (file)
@@ -70,6 +70,8 @@ htsmsg_t * bouquet_class_get_list(void *o, const char *lang);
 bouquet_t * bouquet_create(const char *uuid, htsmsg_t *conf,
                            const char *name, const char *src);
 
+void bouquet_delete(bouquet_t *bq);
+
 void bouquet_destroy_by_service(service_t *t);
 void bouquet_destroy_by_channel_tag(channel_tag_t *ct);
 
index bf823f2a201a1e12ec9bdc337c0d6367f6eca615..12d421fad2519dfaf1354ce5214ff6ebcbb168d1 100644 (file)
@@ -23,6 +23,7 @@
 #include "settings.h"
 #include "htsstr.h"
 #include "channels.h"
+#include "bouquet.h"
 
 #include <sys/socket.h>
 #include <sys/types.h>
@@ -81,6 +82,43 @@ 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];
+  snprintf(buf, sizeof(buf), "iptv-network://%s", idnode_uuid_as_sstr(&in->mn_id));
+  return bouquet_find_by_source(in->in_url, 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;
+  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, 0);
+      seen++;
+    }
+  bouquet_completed(bq, seen);
+}
+
+void
+iptv_bouquet_trigger(iptv_network_t *in, int timeout)
+{
+  gtimer_arm(&in->in_bouquet_timer, iptv_bouquet_update, in, timeout);
+}
+
+
 /* **************************************************************************
  * IPTV input
  * *************************************************************************/
@@ -90,6 +128,7 @@ iptv_input_class_get_title ( idnode_t *self, const char *lang )
 {
   return tvh_gettext_lang(lang, N_("IPTV"));
 }
+
 extern const idclass_t mpegts_input_class;
 const idclass_t iptv_input_class = {
   .ic_super      = &mpegts_input_class,
@@ -485,13 +524,17 @@ iptv_network_delete ( mpegts_network_t *mn, int delconf )
   char *icon_url = in->in_icon_url;
   char *icon_url_sane = in->in_icon_url_sane;
 
+  gtimer_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_sstr(&in->mn_id));
+    bouquet_delete(iptv_bouquet_get(in, 0));
+  }
 
   /* delete */
   free(in->in_remove_args);
@@ -594,6 +637,22 @@ 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)
 {
@@ -617,6 +676,13 @@ 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"),
+      .off      = offsetof(iptv_network_t, in_bouquet),
+      .notify   = iptv_auto_network_class_notify_bouquet,
+    },
     {
       .type     = PT_STR,
       .id       = "ctx_charset",
index 85008f57be502f528db9b63f288364fcffea43a1..694587f9cfb2413d907f529f8d413f7db6674410 100644 (file)
@@ -190,6 +190,7 @@ iptv_auto_network_process_m3u_item(iptv_network_t *in,
         change = 1;
       }
       if (im->mm_iptv_chnum != chnum) {
+        iptv_bouquet_trigger(in, 0); /* propagate LCN change */
         im->mm_iptv_chnum = chnum;
         change = 1;
       }
index 2714a9f224be14195be351ed0f562e07e6f37550..5415a26afe52ff1bf165c2ad5ada62f2fb69fda0 100644 (file)
@@ -36,6 +36,8 @@
 #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;
@@ -81,6 +83,8 @@ struct iptv_network
 
   char    *in_url;
   char    *in_url_sane;
+  int      in_bouquet;
+  gtimer_t in_bouquet_timer;
   char    *in_ctx_charset;
   int64_t  in_channel_number;
   uint32_t in_refetch_period;
@@ -155,6 +159,8 @@ extern const idclass_t iptv_auto_network_class;
 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 c3528b381a0b58166ae3afc11e1ad23dac2fda8d..2d2b3762a3d12eb3125edb0cb3d7b491ab850529 100644 (file)
@@ -116,6 +116,7 @@ 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,
@@ -133,5 +134,8 @@ 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;
 }