]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
mpegts: make the mapping of network<->input N<->N
authorAdam Sutton <dev@adamsutton.me.uk>
Mon, 17 Mar 2014 17:40:37 +0000 (17:40 +0000)
committerAdam Sutton <dev@adamsutton.me.uk>
Tue, 18 Mar 2014 21:46:11 +0000 (21:46 +0000)
I've rejected doing this for ages, however there are real limitations with
not being able to do this. And I've specifically come across one while thinking
about how some IPTV changes would be handled.

This will probably result in a break to peoples config, I will try and mitigate
this.

src/input/mpegts.h
src/input/mpegts/mpegts_input.c
src/input/mpegts/mpegts_network.c

index 6370b49cc03169f2e6032e1a9833b59fc554b782..1e537316ea814b0789d6ec2f66d3a5dfaa7e9578 100644 (file)
@@ -40,12 +40,14 @@ typedef struct mpegts_mux_instance  mpegts_mux_instance_t;
 typedef struct mpegts_mux_sub       mpegts_mux_sub_t;
 typedef struct mpegts_input         mpegts_input_t;
 typedef struct mpegts_table_feed    mpegts_table_feed_t;
+typedef struct mpegts_network_link  mpegts_network_link_t;
 
 /* Lists */
-typedef LIST_HEAD (,mpegts_network)                mpegts_network_list_t;
-typedef LIST_HEAD (mpegts_input_list,mpegts_input) mpegts_input_list_t;
-typedef TAILQ_HEAD(mpegts_mux_queue,mpegts_mux)    mpegts_mux_queue_t;
-typedef LIST_HEAD (mpegts_mux_list,mpegts_mux)     mpegts_mux_list_t;
+typedef LIST_HEAD (,mpegts_network)             mpegts_network_list_t;
+typedef LIST_HEAD (,mpegts_input)               mpegts_input_list_t;
+typedef TAILQ_HEAD(mpegts_mux_queue,mpegts_mux) mpegts_mux_queue_t;
+typedef LIST_HEAD (,mpegts_mux)                 mpegts_mux_list_t;
+typedef LIST_HEAD (,mpegts_network_link)        mpegts_network_link_list_t;
 TAILQ_HEAD(mpegts_table_feed_queue, mpegts_table_feed);
 
 /* Classes */
@@ -190,6 +192,16 @@ void mpegts_psi_section_reassemble
  * Logical network
  * *************************************************************************/
 
+/* Network/Input linkage */
+struct mpegts_network_link
+{
+  int                             mnl_mark;
+  mpegts_input_t                  *mnl_input;
+  mpegts_network_t                *mnl_network;
+  LIST_ENTRY(mpegts_network_link) mnl_mn_link;
+  LIST_ENTRY(mpegts_network_link) mnl_mi_link;
+};
+
 /* Network */
 struct mpegts_network
 {
@@ -212,7 +224,7 @@ struct mpegts_network
   /*
    * Inputs
    */
-  mpegts_input_list_t     mn_inputs;
+  mpegts_network_link_list_t   mn_inputs;
 
   /*
    * Multiplexes
@@ -419,8 +431,7 @@ struct mpegts_input
 
   LIST_ENTRY(mpegts_input) mi_global_link;
 
-  mpegts_network_t *mi_network;
-  LIST_ENTRY(mpegts_input) mi_network_link;
+  mpegts_network_link_list_t mi_networks;
 
   LIST_HEAD(,mpegts_mux_instance) mi_mux_active;
 
@@ -509,13 +520,21 @@ void mpegts_input_delete ( mpegts_input_t *mi, int delconf );
 
 #define mpegts_input_find(u) idnode_find(u, &mpegts_input_class);
 
-void mpegts_input_set_network ( mpegts_input_t *mi, mpegts_network_t *mn );
+int mpegts_input_set_networks ( mpegts_input_t *mi, htsmsg_t *msg );
+
+int mpegts_input_add_network  ( mpegts_input_t *mi, mpegts_network_t *mn );
 
 void mpegts_input_open_service ( mpegts_input_t *mi, mpegts_service_t *s, int init );
 void mpegts_input_close_service ( mpegts_input_t *mi, mpegts_service_t *s );
 
 void mpegts_input_status_timer ( void *p );
 
+/* TODO: exposing these class methods here is a bit of a hack */
+const void *mpegts_input_class_network_get  ( void *o );
+int         mpegts_input_class_network_set  ( void *o, const void *p );
+htsmsg_t   *mpegts_input_class_network_enum ( void *o );
+char       *mpegts_input_class_network_rend ( void *o );
+
 void mpegts_network_register_builder
   ( const idclass_t *idc,
     mpegts_network_t *(*build)(const idclass_t *idc, htsmsg_t *conf) );
index 2c053bd0f5cef5eef0796186fc3b2e57eff78390..9d715ac39b1f66313babe608d7803102db2673a1 100644 (file)
 #include "subscriptions.h"
 #include "atomic.h"
 #include "notify.h"
+#include "idnode.h"
 
 #include <pthread.h>
 #include <assert.h>
 
 SKEL_DECLARE(mpegts_pid_sub_skel, mpegts_pid_sub_t);
 
+static void
+mpegts_input_del_network ( mpegts_network_link_t *mnl );
 
 /* **************************************************************************
  * Class definition
@@ -43,6 +46,59 @@ mpegts_input_class_get_title ( idnode_t *in )
   return buf;
 }
 
+const void *
+mpegts_input_class_network_get ( void *obj )
+{
+  mpegts_network_link_t *mnl;  
+  mpegts_input_t *mi = obj;
+  htsmsg_t       *l  = htsmsg_create_list();
+
+  LIST_FOREACH(mnl, &mi->mi_networks, mnl_mi_link)
+    htsmsg_add_str(l, NULL, idnode_uuid_as_str(&mnl->mnl_network->mn_id));
+
+  return l;
+}
+
+int
+mpegts_input_class_network_set ( void *obj, const void *p )
+{
+  return mpegts_input_set_networks(obj, (htsmsg_t*)p);
+}
+
+htsmsg_t *
+mpegts_input_class_network_enum ( void *obj )
+{
+  htsmsg_t *p, *m;
+
+  p = htsmsg_create_map();
+  htsmsg_add_str (p, "uuid",    idnode_uuid_as_str((idnode_t*)obj));
+  htsmsg_add_bool(p, "enum",    1);
+
+  m = htsmsg_create_map();
+  htsmsg_add_str (m, "type",    "api");
+  htsmsg_add_str (m, "uri",     "mpegts/input/network_list");
+  htsmsg_add_str (m, "event",   "mpegts_network");
+  htsmsg_add_msg (m, "params",  p);
+  return m;
+}
+
+char *
+mpegts_input_class_network_rend ( void *obj )
+{
+  char *str;
+  mpegts_network_link_t *mnl;  
+  mpegts_input_t *mi = obj;
+  htsmsg_t        *l = htsmsg_create_list();
+
+  LIST_FOREACH(mnl, &mi->mi_networks, mnl_mi_link)
+    htsmsg_add_str(l, NULL, idnode_get_title(&mnl->mnl_network->mn_id));
+
+  str = htsmsg_list_2_csv(l);
+  htsmsg_destroy(l);
+
+  return str;
+}
+
 const idclass_t mpegts_input_class =
 {
   .ic_class      = "mpegts_input",
@@ -71,6 +127,16 @@ const idclass_t mpegts_input_class =
       .off      = offsetof(mpegts_input_t, mi_name),
       .notify   = idnode_notify_title_changed,
     },
+    {
+      .type     = PT_STR,
+      .id       = "networks",
+      .name     = "Networks",
+      .islist   = 1,
+      .set      = mpegts_input_class_network_set,
+      .get      = mpegts_input_class_network_get,
+      .list     = mpegts_input_class_network_enum,
+      .rend     = mpegts_input_class_network_rend,
+    },
     {}
   }
 };
@@ -711,7 +777,9 @@ mpegts_input_create0
 void
 mpegts_input_delete ( mpegts_input_t *mi, int delconf )
 {
-  mpegts_input_set_network(mi, NULL);
+  mpegts_network_link_t *mnl;
+  while ((mnl = LIST_FIRST(&mi->mi_networks)))
+    mpegts_input_del_network(mnl);
   idnode_unlink(&mi->ti_id);
   pthread_mutex_destroy(&mi->mi_delivery_mutex);
   pthread_cond_destroy(&mi->mi_table_feed_cond);
@@ -728,27 +796,71 @@ mpegts_input_save ( mpegts_input_t *mi, htsmsg_t *m )
   idnode_save(&mi->ti_id, m);
 }
 
-void
-mpegts_input_set_network ( mpegts_input_t *mi, mpegts_network_t *mn )
+int
+mpegts_input_add_network ( mpegts_input_t *mi, mpegts_network_t *mn )
 {
-  char buf1[256], buf2[265];
-  if (mi->mi_network == mn) return;
-  *buf1 = *buf2 = 0;
-  if (mi->mi_display_name) {
-    mi->mi_display_name(mi, buf1, sizeof(buf1));
+  mpegts_network_link_t *mnl;
+
+  /* Find existing */
+  LIST_FOREACH(mnl, &mi->mi_networks, mnl_mi_link)
+    if (mnl->mnl_network == mn)
+      break;
+
+  /* Clear mark */
+  if (mnl) {
+    mnl->mnl_mark = 0;
+    return 0;
   }
-  if (mi->mi_network) {
-    mi->mi_network->mn_display_name(mi->mi_network, buf2, sizeof(buf2));
-    LIST_REMOVE(mi, mi_network_link);
-    tvhdebug("mpegts", "%s - remove network %s", buf1, buf2);
-    mi->mi_network = NULL;
+
+  /* Create new */
+  mnl = calloc(1, sizeof(mpegts_network_link_t));
+  mnl->mnl_input    = mi;
+  mnl->mnl_network  = mn;
+  LIST_INSERT_HEAD(&mi->mi_networks, mnl, mnl_mi_link);
+  LIST_INSERT_HEAD(&mn->mn_inputs,   mnl, mnl_mn_link);
+  idnode_notify_simple(&mnl->mnl_network->mn_id);
+  return 1;
+}
+
+static void
+mpegts_input_del_network ( mpegts_network_link_t *mnl )
+{
+  idnode_notify_simple(&mnl->mnl_network->mn_id);
+  LIST_REMOVE(mnl, mnl_mn_link);
+  LIST_REMOVE(mnl, mnl_mi_link);
+  free(mnl);
+}
+
+int
+mpegts_input_set_networks ( mpegts_input_t *mi, htsmsg_t *msg )
+{
+  int save = 0;
+  const char *str;
+  htsmsg_field_t *f;
+  mpegts_network_t *mn;
+  mpegts_network_link_t *mnl, *nxt;
+  
+  /* Mark for deletion */
+  LIST_FOREACH(mnl, &mi->mi_networks, mnl_mi_link)
+    mnl->mnl_mark = 1;
+
+  /* Link */
+  HTSMSG_FOREACH(f, msg) {
+    if (!(str = htsmsg_field_get_str(f))) continue;
+    if (!(mn = mpegts_network_find(str))) continue;
+    save |= mpegts_input_add_network(mi, mn);
   }
-  if (mn) {
-    mn->mn_display_name(mn, buf2, sizeof(buf2));
-    mi->mi_network = mn;
-    LIST_INSERT_HEAD(&mn->mn_inputs, mi, mi_network_link);
-    tvhdebug("mpegts", "%s - added network %s", buf1, buf2);
+
+  /* Unlink */
+  for (mnl = LIST_FIRST(&mi->mi_networks); mnl != NULL; mnl = nxt) {
+    nxt = LIST_NEXT(mnl, mnl_mi_link);
+    if (mnl->mnl_mark) {
+      mpegts_input_del_network(mnl);
+      save = 1;
+    }
   }
+  
+  return save;
 }
 
 /******************************************************************************
index f531e6a93932239a0951f271c97fb5e9b401c1d3..b62cffcd1cb56a4e0977e542b242a84a0c20648a 100644 (file)
@@ -208,12 +208,21 @@ mpegts_network_mux_create2
   return NULL;
 }
 
+static void
+mpegts_network_link_delete ( mpegts_network_link_t *mnl )
+{
+  idnode_notify_simple(&mnl->mnl_input->ti_id);
+  LIST_REMOVE(mnl, mnl_mn_link);
+  LIST_REMOVE(mnl, mnl_mi_link);
+  free(mnl);
+}
+
 void
 mpegts_network_delete
   ( mpegts_network_t *mn, int delconf )
 {
-  mpegts_input_t *mi;
   mpegts_mux_t *mm;
+  mpegts_network_link_t *mnl;
 
   /* Remove from global list */
   LIST_REMOVE(mn, mn_global_link);
@@ -231,8 +240,8 @@ mpegts_network_delete
   gtimer_disarm(&mn->mn_initial_scan_timer);
 
   /* Remove from input */
-  while ((mi = LIST_FIRST(&mn->mn_inputs)))
-    mpegts_input_set_network(mi, NULL);
+  while ((mnl = LIST_FIRST(&mn->mn_inputs)))
+    mpegts_network_link_delete(mnl);
 
   /* Free memory */
   idnode_unlink(&mn->mn_id);