]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
dvbreorg WIP
authorAndreas Öman <andreas@lonelycoder.com>
Thu, 17 Jan 2013 15:21:55 +0000 (16:21 +0100)
committerAndreas Öman <andreas@lonelycoder.com>
Thu, 17 Jan 2013 15:21:55 +0000 (16:21 +0100)
Initial scan now works again

We have a new idnode system that can give an entity a UUID which then can
be looked up externally (webui, etc). Good when browsing stuff
The UUID is supposed to be persisted on on disk when saving enteties

24 files changed:
Makefile
src/dvb/dvb.c
src/dvb/dvb.h
src/dvb/dvb_adapter.c
src/dvb/dvb_fe.c
src/dvb/dvb_input_filtered.c
src/dvb/dvb_multiplex.c
src/dvb/dvb_network.c
src/dvb/dvb_service.c
src/dvb/dvb_tables.c
src/epggrab/otamux.c
src/filebundle.c
src/idnode.c [new file with mode: 0644]
src/idnode.h [new file with mode: 0644]
src/iptv_input.c
src/main.c
src/service.c
src/service.h
src/streaming.c
src/tvheadend.h
src/webui/extjs.c
src/webui/extjs_dvb.c
src/webui/static/app/dvb_networks.js [new file with mode: 0644]
src/webui/webui.c

index a4e63011eaffdae2b55ecf2984d8d07648195a78..3714576300eac04f56653c5de0795228644e4ca4 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -63,6 +63,7 @@ endif
 # Core
 #
 SRCS =  src/main.c \
+       src/idnode.c \
        src/utils.c \
        src/wrappers.c \
        src/version.c \
index 9e3775b3156683d3db32895224cb93602912aa21..44e905d5115f31d4a9c01ef35368db3479f1fcb7 100644 (file)
@@ -26,5 +26,6 @@ void
 dvb_init(uint32_t adapter_mask, const char *rawfile)
 {
   dvb_charset_init();
+  dvb_network_init();
   dvb_adapter_init(adapter_mask, rawfile);
 }
index 4c4594b2b829d3e1596e5b0002802d35fa864e70..aa08aff037babba1aad9e97e2e7421a15ebb1dd5 100644 (file)
@@ -24,6 +24,7 @@
 #include <pthread.h>
 #include "htsmsg.h"
 #include "psi.h"
+#include "idnode.h"
 
 struct service;
 struct th_dvb_table;
@@ -35,7 +36,7 @@ struct th_dvb_mux_instance;
  (DVB_VER_INT(DVB_API_VERSION,  DVB_API_VERSION_MINOR) >= DVB_VER_INT(maj, min))
 
 TAILQ_HEAD(th_dvb_adapter_queue, th_dvb_adapter);
-RB_HEAD(th_dvb_mux_instance_tree, th_dvb_mux_instance);
+LIST_HEAD(th_dvb_adapter_list, th_dvb_adapter);
 TAILQ_HEAD(th_dvb_mux_instance_queue, th_dvb_mux_instance);
 LIST_HEAD(th_dvb_mux_instance_list, th_dvb_mux_instance);
 TAILQ_HEAD(dvb_satconf_queue, dvb_satconf);
@@ -89,11 +90,14 @@ typedef struct dvb_mux_conf {
  *
  */
 typedef struct dvb_network {
+  idnode_t dn_id;
 
   LIST_ENTRY(dvb_network) dn_global_link;
 
-  struct dvb_mux_queue dn_initial_scan_queue;
-  int dn_initial_num_mux;
+  struct dvb_mux_queue dn_initial_scan_pending_queue;
+  struct dvb_mux_queue dn_initial_scan_current_queue;
+  int dn_initial_scan_num_mux;
+  gtimer_t dn_initial_scan_timer;
 
   struct dvb_mux *dn_mux_epg;
 
@@ -101,13 +105,11 @@ typedef struct dvb_network {
 
   struct dvb_mux_list dn_muxes;
 
-  gtimer_t dn_mux_scanner_timer;
-
   uint32_t dn_disable_pmt_monitor;
   uint32_t dn_autodiscovery;
   uint32_t dn_nitoid;
 
-  char *dn_uuid;
+  struct th_dvb_adapter_list dn_adapters;
 
 } dvb_network_t;
 
@@ -117,7 +119,7 @@ typedef struct dvb_network {
  *
  */
 typedef struct dvb_mux {
-
+  idnode_t dm_id;
   LIST_ENTRY(dvb_mux) dm_network_link;
   dvb_network_t *dm_dn;
 
@@ -132,14 +134,20 @@ typedef struct dvb_mux {
 
   TAILQ_HEAD(, epggrab_ota_mux) dm_epg_grab;
 
+  gtimer_t dm_initial_scan_timeout;
+
   TAILQ_ENTRY(dvb_mux) dm_scan_link;
-  struct dvb_mux_queue *dm_scan_queue;
+  enum {
+    DM_SCAN_DONE,     // All done
+    DM_SCAN_PENDING,  // Waiting to be tuned for initial scan
+    DM_SCAN_CURRENT,  // Currently tuned for initial scan
+  } dm_scan_status;
 
   LIST_HEAD(, th_dvb_table) dm_tables;
   int dm_num_tables;
 
   TAILQ_HEAD(, th_dvb_table) dm_table_queue;
-  int dm_table_initial;
+  //  int dm_table_initial;
 
   struct th_dvb_mux_instance *dm_current_tdmi;
 
@@ -148,8 +156,6 @@ typedef struct dvb_mux {
   // Derived from dm_conf (more or less)
   char *dm_local_identifier;
 
-  char *dm_uuid;
-
   int dm_enabled;
 
 } dvb_mux_t;
@@ -193,6 +199,8 @@ typedef struct th_dvb_mux_instance {
   int tdmi_tune_failed; // Adapter failed to tune this frequency
                         // Don't try again
 
+  int tdmi_weight;
+
   struct th_subscription_list tdmi_subscriptions;
 
 } th_dvb_mux_instance_t;
@@ -226,6 +234,7 @@ typedef struct th_dvb_adapter {
   TAILQ_ENTRY(th_dvb_adapter) tda_global_link;
 
   dvb_network_t *tda_dn;
+  LIST_ENTRY(th_dvb_adapter) tda_network_link;
 
   struct th_dvb_mux_instance_list tda_tdmis;
 
@@ -479,6 +488,8 @@ dvb_mux_t *dvb_mux_find(dvb_network_t *dn, const char *netname, uint16_t onid,
                         uint16_t tsid, int enabled);
 
 
+void dvb_mux_initial_scan_done(dvb_mux_t *dm);
+
 /**
  * DVB Transport (aka DVB service)
  */
@@ -507,14 +518,12 @@ void dvb_service_notify(struct service *t);
 
 void dvb_service_notify_by_adapter(th_dvb_adapter_t *tda);
 
-htsmsg_t *dvb_service_build_msg(struct service *t);
-
 /**
  * DVB Frontend
  */
-int dvb_fe_tune(dvb_mux_t *dm, const char *reason);
+int dvb_fe_tune(dvb_mux_t *dm, const char *reason, int weight);
 
-void dvb_fe_stop(th_dvb_adapter_t *tda, int retune);
+//void dvb_fe_stop(th_dvb_adapter_t *tda, int retune);
 
 
 /**
@@ -551,9 +560,15 @@ void dvb_table_release(th_dvb_table_t *tdt);
 /**
  *
  */
-dvb_network_t *dvb_network_create(int fe_type);
+dvb_network_t *dvb_network_create(int fe_type, const char *uuid);
+
+//void dvb_network_mux_scanner(void *aux);
+
+void dvb_network_init(void);
+
+idnode_t **dvb_network_root(void);
 
-void dvb_network_mux_scanner(void *aux);
+void dvb_network_schedule_initial_scan(dvb_network_t *dn);
 
 
 /**
index b7029fb3aaf2b60684e82cb3df308ba5c9ef7753..d43938db1724bb961d2a7a29a422d2a47814b182 100644 (file)
@@ -46,7 +46,6 @@
 #include "diseqc.h"
 
 struct th_dvb_adapter_queue dvb_adapters;
-struct th_dvb_mux_instance_tree dvb_muxes;
 static void *dvb_adapter_input_dvr(void *aux);
 
 
@@ -280,6 +279,20 @@ dvb_adapter_set_extrapriority(th_dvb_adapter_t *tda, int extrapriority)
   tda_save(tda);
 }
 
+
+/**
+ *
+ */
+static void
+dvb_adapter_set_network(th_dvb_adapter_t *tda, const char *uuid)
+{
+  dvb_network_t *dn = LIST_FIRST(&dvb_networks);
+  tda->tda_dn = dn;
+  LIST_INSERT_HEAD(&dn->dn_adapters, tda, tda_network_link);
+}
+
+
+
 /**
  *
  */
@@ -402,7 +415,7 @@ tda_add(int adapter_num)
     close(fe);
 
   tda->tda_fe_type = tda->tda_fe_info->type;
-  tda->tda_dn = dvb_network_create(tda->tda_fe_type);
+  dvb_adapter_set_network(tda, NULL);
 
   snprintf(buf, sizeof(buf), "%s_%s", tda->tda_rootpath,
           tda->tda_fe_info->name);
index dafca7147f99dd24e335ca59b089578526aa0dc9..ba05ed4f1660708dfc4a0ab7983c397e11291b98 100644 (file)
@@ -107,6 +107,7 @@ dvb_fe_monitor(void *aux)
   /**
    * Read out front end status
    */
+
   if(ioctl(tda->tda_fe_fd, FE_READ_STATUS, &fe_status))
     fe_status = 0;
 
@@ -254,6 +255,7 @@ dvb_fe_monitor(void *aux)
 }
 
 
+#if 0
 /**
  * Stop the given TDMI
  */
@@ -266,16 +268,8 @@ dvb_fe_stop(th_dvb_adapter_t *tda, int retune)
   assert(tdmi != NULL);
   dvb_mux_t *dm = tdmi->tdmi_mux;
 
-  if(dm->dm_table_initial) {
-    dm->dm_table_initial = 0;
-    dm->dm_dn->dn_initial_num_mux--;
-    dvb_mux_save(dm);
-  }
-
   dvb_table_flush_all(dm);
 
-  assert(dm->dm_scan_queue == NULL);
-
   epggrab_mux_stop(dm, 0);
 
 #if 0  /// XXX(dvbreorg)
@@ -285,6 +279,9 @@ dvb_fe_stop(th_dvb_adapter_t *tda, int retune)
   }
 #endif
 }
+#endif
+
+
 
 #if DVB_API_VERSION >= 5
 
@@ -342,9 +339,8 @@ static struct dtv_properties clear_cmdseq = {
  *
  */
 static int
-dvb_fe_tune_s2(th_dvb_mux_instance_t *tdmi, dvb_mux_conf_t *dmc)
+dvb_fe_tune_s2(th_dvb_adapter_t *tda, dvb_mux_conf_t *dmc)
 {
-  th_dvb_adapter_t *tda = tdmi->tdmi_adapter;
   struct dvb_frontend_parameters *p = &dmc->dmc_fe_params;
   int r;
   
@@ -388,47 +384,151 @@ dvb_fe_tune_s2(th_dvb_mux_instance_t *tdmi, dvb_mux_conf_t *dmc)
 
 #endif
 
+
 /**
- *
+ * These are created on the fly
  */
-int
-dvb_fe_tune(dvb_mux_t *dm, const char *reason)
+static void
+dvb_create_tdmis(dvb_mux_t *dm)
 {
+  th_dvb_mux_instance_t *tdmi;
   dvb_network_t *dn = dm->dm_dn;
+  th_dvb_adapter_t *tda;
+
+  LIST_FOREACH(tda, &dn->dn_adapters, tda_network_link) {
+
+    LIST_FOREACH(tdmi, &dm->dm_tdmis, tdmi_mux_link) {
+      if(tdmi->tdmi_adapter != NULL)
+        break;
+    }
 
-  th_dvb_mux_instance_t *tdmi = NULL; // dm->dm_tdmi;
+    if(tdmi == NULL) {
+      tdmi = calloc(1, sizeof(th_dvb_mux_instance_t));
+      tdmi->tdmi_adapter = tda;
+      tdmi->tdmi_mux = dm;
+      LIST_INSERT_HEAD(&tda->tda_tdmis, tdmi, tdmi_adapter_link);
+      LIST_INSERT_HEAD(&dm->dm_tdmis,   tdmi, tdmi_mux_link);
+    }
+  }
+}
+
+
+
+/**
+ *
+ */
+static void
+dvb_mux_stop(th_dvb_mux_instance_t *tdmi)
+{
+  dvb_mux_t *dm = tdmi->tdmi_mux;
   th_dvb_adapter_t *tda = tdmi->tdmi_adapter;
+  assert(dm->dm_current_tdmi == tdmi);
+  assert(tda->tda_current_tdmi == tdmi);
+
+  dvb_table_flush_all(dm);
+  epggrab_mux_stop(dm, 0);
+
+  assert(dm->dm_scan_status == DM_SCAN_DONE);
+
+  dm->dm_current_tdmi = NULL;
+  tda->tda_current_tdmi = NULL;
+
+  printf("NEED TO TAKE CARE OF SERVICES in dvb_mux_stop\n");
+}
+
+
+/**
+ *
+ */
+static int
+tdmi_compute_weight(const th_dvb_mux_instance_t *tdmi)
+{
+  const dvb_mux_t *dm = tdmi->tdmi_mux;
+  if(dm->dm_scan_status == DM_SCAN_CURRENT)
+    return 1;
+  return 0;
+}
+
+
+/**
+ *
+ */
+static void
+dvb_mux_initial_scan_timeout(void *aux)
+{
+  dvb_mux_t *dm = aux;
+  char buf[100];
+
+  dvb_mux_nicename(buf, sizeof(buf), dm);
+  tvhlog(LOG_DEBUG, "dvb", "Initial scan timed out for \"%s\"", buf);
+
+  dvb_mux_initial_scan_done(dm);
+}
+
+
+/**
+ *
+ */
+int
+dvb_fe_tune(dvb_mux_t *dm, const char *reason, int weight)
+{
+  dvb_network_t *dn = dm->dm_dn;
 
   // copy dmc, cause frequency may be change with FE_QPSK
   dvb_mux_conf_t dmc = dm->dm_conf;
   dvb_frontend_parameters_t* p = &dmc.dmc_fe_params;
-  
+  th_dvb_mux_instance_t *tdmi;
+
   char buf[256];
   int r;
+
+  assert(dm->dm_current_tdmi == NULL);
 
   lock_assert(&global_lock);
 
-  free(tda->tda_tune_reason);
-  tda->tda_tune_reason = strdup(reason);
+  dvb_create_tdmis(dm);
 
-  if(tda->tda_current_tdmi == tdmi) {
-    dvb_adapter_notify(tda);
-    return 0;
-  }
+  retry:
+  // Figure which adapter to use
+  LIST_FOREACH(tdmi, &dm->dm_tdmis, tdmi_mux_link)
+    if(!tdmi->tdmi_tune_failed && tdmi->tdmi_adapter->tda_current_tdmi == NULL)
+      break;
+
+  if(tdmi == NULL) {
+    // None available, need to strike one out
+    LIST_FOREACH(tdmi, &dm->dm_tdmis, tdmi_mux_link) {
+      if(tdmi->tdmi_tune_failed)
+        continue;
+
+      th_dvb_adapter_t *tda = tdmi->tdmi_adapter;
+      th_dvb_mux_instance_t *t2 = tda->tda_current_tdmi;
+      assert(t2 != NULL);
+      assert(t2 != tdmi);
+
+      if(tdmi_compute_weight(t2) < weight) {
+        dvb_mux_stop(t2);
+        break;
+      }
+    }
+
+    if(tdmi == NULL)
+      return SM_CODE_NO_FREE_ADAPTER;
 
-  if(dm->dm_scan_queue != NULL) {
-    TAILQ_REMOVE(dm->dm_scan_queue, dm, dm_scan_link);
-    dm->dm_scan_queue = NULL;
   }
 
-  if(tda->tda_current_tdmi != NULL)
-    dvb_fe_stop(tda, 1);
-  else
-    dvb_adapter_start(tda);
-      
+  th_dvb_adapter_t *tda = tdmi->tdmi_adapter;
+
+  dvb_adapter_start(tda);
+
+  assert(tda->tda_current_tdmi == NULL);
+
+  free(tda->tda_tune_reason);
+  tda->tda_tune_reason = strdup(reason);
+
+  tdmi->tdmi_weight = weight;
+
   if(tda->tda_fe_type == FE_QPSK) {
-       
+
     /* DVB-S */
     int port, lowfreq, hifreq, switchfreq, hiband, pol, dbsbs;
 
@@ -486,11 +586,11 @@ dvb_fe_tune(dvb_mux_t *dm, const char *reason)
       dvb_mux_fec2str(p->u.qpsk.fec_inner), dvb_mux_delsys2str(dmc.dmc_fe_delsys), 
       dvb_mux_qam2str(dmc.dmc_fe_modulation), reason);
   
-    r = dvb_fe_tune_s2(tdmi, &dmc);
+    r = dvb_fe_tune_s2(tda, &dmc);
   } else
 #endif
   {
-    tvhlog(LOG_DEBUG, "dvb", "\"%s\" tuning to \"%s\" (%s)", tda->tda_rootpath, buf, reason);
+    tvhlog(LOG_DEBUG, "dvb", "\"%s\" tuning to \"%s\" (%s) fd:%d", tda->tda_rootpath, buf, reason, tda->tda_fe_fd);
     r = ioctl(tda->tda_fe_fd, FE_SET_FRONTEND, p);
   }
 
@@ -499,24 +599,26 @@ dvb_fe_tune(dvb_mux_t *dm, const char *reason)
      " -- Front configuration failed -- %s, frequency: %u",
      tda->tda_rootpath, buf, strerror(errno), p->frequency);
 
-    /* Remove from initial scan set */
-    if(dm->dm_table_initial) {
-      dm->dm_table_initial = 0;
-      dn->dn_initial_num_mux--;
-    }
-
     /* Mark as bad */
     tdmi->tdmi_tune_failed = 1;
-    return SM_CODE_TUNING_FAILED;
+    goto retry;
   }
 
   tda->tda_current_tdmi = tdmi;
+  dm->dm_current_tdmi = tdmi;
+  if(dm->dm_scan_status == DM_SCAN_PENDING) {
+    TAILQ_REMOVE(&dn->dn_initial_scan_pending_queue, dm, dm_scan_link);
+    dm->dm_scan_status = DM_SCAN_CURRENT;
+    TAILQ_INSERT_TAIL(&dn->dn_initial_scan_current_queue, dm, dm_scan_link);
 
-  gtimer_arm(&tda->tda_fe_monitor_timer, dvb_fe_monitor, tda, 1);
+    gtimer_arm(&dm->dm_initial_scan_timeout, dvb_mux_initial_scan_timeout, dm, 10);
+  }
 
 
-  dvb_table_add_default(tdmi->tdmi_mux);
-  epggrab_mux_start(tdmi->tdmi_mux);
+  gtimer_arm(&tda->tda_fe_monitor_timer, dvb_fe_monitor, tda, 1);
+
+  dvb_table_add_default(dm);
+  epggrab_mux_start(dm);
 
   dvb_adapter_notify(tda);
   return 0;
index 68abf7bf5e5e3fd7a6adf5aaf85bf480f134dcfc..9040dcd749ac59149ac1737679a93926515bd675 100644 (file)
@@ -59,7 +59,7 @@ open_service(th_dvb_adapter_t *tda, service_t *s)
       st->es_demuxer_fd = -1;
       tvhlog(LOG_ERR, "dvb",
             "\"%s\" unable to open demuxer \"%s\" for pid %d -- %s",
-            s->s_uuid, tda->tda_demux_path, 
+            s->s_nicename, tda->tda_demux_path, 
             st->es_pid, strerror(errno));
       continue;
     }
@@ -74,7 +74,7 @@ open_service(th_dvb_adapter_t *tda, service_t *s)
     if(ioctl(fd, DMX_SET_PES_FILTER, &dmx_param)) {
       tvhlog(LOG_ERR, "dvb",
             "\"%s\" unable to configure demuxer \"%s\" for pid %d -- %s",
-            s->s_uuid, tda->tda_demux_path, 
+            s->s_nicename, tda->tda_demux_path, 
             st->es_pid, strerror(errno));
       close(fd);
       fd = -1;
index 6942483710b4f03142bd9b2171c4d07cff39c23e..49fe59f3433585af0aedf7779ada455955033083 100644 (file)
@@ -46,8 +46,6 @@
 #include "subscriptions.h"
 #include "epggrab.h"
 
-struct th_dvb_mux_instance_tree dvb_muxes;
-
 static struct strtab muxfestatustab[] = {
   { "Unknown",      TDMI_FE_UNKNOWN },
   { "No signal",    TDMI_FE_NO_SIGNAL },
@@ -58,18 +56,51 @@ static struct strtab muxfestatustab[] = {
   { "OK",           TDMI_FE_OK },
 };
 
+
+
+static htsmsg_t *dvb_mux_serialize(struct idnode *self, int full);
+static idnode_t **dvb_mux_get_childs(struct idnode *self);
+
+static const idclass_t dvb_mux_class = {
+  .ic_class = "dvbmux",
+  .ic_serialize = dvb_mux_serialize,
+  .ic_get_childs = dvb_mux_get_childs,
+};
+
+
+
 /**
  *
  */
 static void
 mux_link_initial(dvb_network_t *dn, dvb_mux_t *dm)
 {
-  dm->dm_scan_queue = &dn->dn_initial_scan_queue;
-  TAILQ_INSERT_TAIL(dm->dm_scan_queue, dm, dm_scan_link);
+  assert(dm->dm_scan_status == DM_SCAN_DONE);
 
-  gtimer_arm(&dn->dn_mux_scanner_timer, dvb_network_mux_scanner, dn, 0);
+  dm->dm_scan_status = DM_SCAN_PENDING;
+  TAILQ_INSERT_TAIL(&dn->dn_initial_scan_pending_queue, dm, dm_scan_link);
+  dn->dn_initial_scan_num_mux++;
+  dvb_network_schedule_initial_scan(dn);
 }
 
+
+/**
+ *
+ */
+void
+dvb_mux_initial_scan_done(dvb_mux_t *dm)
+{
+  dvb_network_t *dn = dm->dm_dn;
+  gtimer_disarm(&dm->dm_initial_scan_timeout);
+  assert(dm->dm_scan_status == DM_SCAN_CURRENT);
+  dn->dn_initial_scan_num_mux--;
+  dm->dm_scan_status = DM_SCAN_DONE;
+  TAILQ_REMOVE(&dn->dn_initial_scan_current_queue, dm, dm_scan_link);
+  dvb_network_schedule_initial_scan(dn);
+  dvb_mux_save(dm); // Save to dm_scan_status is persisted
+}
+
+
 /**
  *  Return a readable status text for the given mux
  */
@@ -136,7 +167,7 @@ dcm_compare_conf(int adapter_type,
 dvb_mux_t *
 dvb_mux_create(dvb_network_t *dn, const struct dvb_mux_conf *dmc,
               uint16_t onid, uint16_t tsid, const char *network,
-               const char *source, int enabled, int initialscan,
+               const char *source, int enabled, int needscan,
                const char *uuid)
 {
   dvb_mux_t *dm;
@@ -186,16 +217,6 @@ dvb_mux_create(dvb_network_t *dn, const struct dvb_mux_conf *dmc,
       save = 1;
     }
 
-#if 0 // XXX(dvbreorg)
-    /* HACK - load old transports and remove old mux config */
-    if(identifier) {
-      save = 1;
-      dvb_service_load(tdmi, identifier);
-      hts_settings_remove("dvbmuxes/%s/%s",
-                     tda->tda_identifier, identifier);
-    }
-#endif
-
     if(save) {
       char buf[128];
       dvb_mux_save(dm);
@@ -220,6 +241,8 @@ dvb_mux_create(dvb_network_t *dn, const struct dvb_mux_conf *dmc,
   dm->dm_dn = dn;
   LIST_INSERT_HEAD(&dn->dn_muxes, dm, dm_network_link);
 
+  idnode_insert(&dm->dm_id, uuid, &dvb_mux_class);
+
   char identifier[128];
   snprintf(identifier, sizeof(identifier),
            "%d%s", dmc->dmc_fe_params.frequency,
@@ -231,8 +254,6 @@ dvb_mux_create(dvb_network_t *dn, const struct dvb_mux_conf *dmc,
 
   memcpy(&dm->dm_conf, dmc, sizeof(struct dvb_mux_conf));
 
-  dm->dm_table_initial = initialscan;
-
   if(source != NULL) {
     char buf[128];
     dvb_mux_nicename(buf, sizeof(buf), dm);
@@ -243,8 +264,8 @@ dvb_mux_create(dvb_network_t *dn, const struct dvb_mux_conf *dmc,
 
   dvb_service_load(dm);
 
-  if(enabled && dm->dm_table_initial) {
-    dn->dn_initial_num_mux++;
+  if(enabled && needscan) {
+    dn->dn_initial_scan_num_mux++;
     mux_link_initial(dn, dm);
   }
 
@@ -271,6 +292,7 @@ void
 dvb_mux_destroy(dvb_mux_t *dm)
 {
   th_dvb_mux_instance_t *tdmi;
+  dvb_network_t *dn = dm->dm_dn;
 
   lock_assert(&global_lock);
 
@@ -279,16 +301,25 @@ dvb_mux_destroy(dvb_mux_t *dm)
   while((tdmi = LIST_FIRST(&dm->dm_tdmis)) != NULL)
     dvb_tdmi_destroy(tdmi);
 
-  if(dm->dm_scan_queue != NULL)
-    TAILQ_REMOVE(dm->dm_scan_queue, dm, dm_scan_link);
+  switch(dm->dm_scan_status) {
+  case DM_SCAN_DONE:
+    break;
+  case DM_SCAN_CURRENT:
+    TAILQ_REMOVE(&dn->dn_initial_scan_current_queue, dm, dm_scan_link);
+    gtimer_disarm(&dm->dm_initial_scan_timeout);
+    if(0) // Sorry but i can't resist these whenever i get an oppertunity // andoma
+  case DM_SCAN_PENDING:
+      TAILQ_REMOVE(&dn->dn_initial_scan_pending_queue, dm, dm_scan_link);
+    dn->dn_initial_scan_num_mux--;
+    dvb_network_schedule_initial_scan(dn);
+    break;
+  }
 
-  if(dm->dm_table_initial)
-    dm->dm_dn->dn_initial_num_mux--;
 
   epggrab_mux_delete(dm);
 
   free(dm->dm_local_identifier);
-  free(dm->dm_uuid);
+  idnode_unlink(&dm->dm_id);
   free(dm);
 }
 
@@ -492,7 +523,7 @@ dvb_mux_save(dvb_mux_t *dm)
 
   htsmsg_add_u32(m, "frequency", f->frequency);
 
-  htsmsg_add_u32(m, "initialscan", dm->dm_table_initial);
+  htsmsg_add_u32(m, "needscan", dm->dm_scan_status != DM_SCAN_DONE);
 
   if(dm->dm_default_authority)
     htsmsg_add_str(m, "default_authority", dm->dm_default_authority);
@@ -559,7 +590,7 @@ dvb_mux_save(dvb_mux_t *dm)
   }
 
   hts_settings_save(m, "dvb/networks/%s/muxes/%s/config",
-                    dm->dm_dn->dn_uuid,
+                    idnode_uuid_as_str(&dm->dm_dn->dn_id),
                     dm->dm_local_identifier);
 
   htsmsg_destroy(m);
@@ -575,7 +606,7 @@ dvb_mux_create_by_msg(dvb_network_t *dn, htsmsg_t *m, const char *fname)
   struct dvb_mux_conf dmc;
   const char *s;
   int r;
-  unsigned int onid, tsid, enabled, initscan;
+  unsigned int onid, tsid, enabled;
 
   memset(&dmc, 0, sizeof(dmc));
   dmc.dmc_fe_params.inversion = INVERSION_AUTO;
@@ -694,10 +725,9 @@ dvb_mux_create_by_msg(dvb_network_t *dn, htsmsg_t *m, const char *fname)
   if(htsmsg_get_u32(m, "enabled", &enabled))
     enabled = 1;
 
-  initscan = htsmsg_get_u32_or_default(m, "initialscan", 0);
   dm = dvb_mux_create(dn, &dmc,
                       onid, tsid, htsmsg_get_str(m, "network"), NULL, enabled,
-                      initscan,
+                      htsmsg_get_u32_or_default(m, "needscan", 1),
                       htsmsg_get_str(m, "uuid"));
   if(dm != NULL) {
 
@@ -718,13 +748,16 @@ dvb_mux_load(dvb_network_t *dn)
   htsmsg_field_t *f;
 
   if((l = hts_settings_load_r(1, "dvb/networks/%s/muxes",
-                              dn->dn_uuid)) == NULL)
+                              idnode_uuid_as_str(&dn->dn_id))) == NULL)
     return;
 
   HTSMSG_FOREACH(f, l) {
     if((c = htsmsg_get_map_by_field(f)) == NULL)
       continue;
 
+    if((c = htsmsg_get_map(c, "config")) == NULL)
+       continue;
+
     dvb_mux_create_by_msg(dn, c, f->hmf_name);
   }
   htsmsg_destroy(l);
@@ -765,7 +798,7 @@ dvb_mux_set_tsid(dvb_mux_t *dm, uint16_t tsid)
   dvb_mux_save(dm);
 
   m = htsmsg_create_map();
-  htsmsg_add_str(m, "uuid", dm->dm_uuid);
+  htsmsg_add_str(m, "uuid", idnode_uuid_as_str(&dm->dm_id));
   htsmsg_add_u32(m, "muxid", dm->dm_transport_stream_id);
   notify_by_msg("dvbMux", m);
 }
@@ -783,7 +816,7 @@ dvb_mux_set_onid(dvb_mux_t *dm, uint16_t onid)
   dvb_mux_save(dm);
 
   m = htsmsg_create_map();
-  htsmsg_add_str(m, "uuid", dm->dm_uuid);
+  htsmsg_add_str(m, "uuid", idnode_uuid_as_str(&dm->dm_id));
   htsmsg_add_u32(m, "onid", dm->dm_network_id);
   notify_by_msg("dvbMux", m);
 }
@@ -917,7 +950,7 @@ dvb_mux_build_msg(dvb_mux_t *dm)
   htsmsg_t *m = htsmsg_create_map();
   char buf[100];
 
-  htsmsg_add_str(m, "uuid", dm->dm_uuid);
+  htsmsg_add_str(m, "uuid", idnode_uuid_as_str(&dm->dm_id));
   htsmsg_add_u32(m, "enabled",  dm->dm_enabled);
   htsmsg_add_str(m, "network", dm->dm_network_name ?: "");
 
@@ -1200,8 +1233,8 @@ dvb_subscription_create_from_tdmi(th_dvb_mux_instance_t *tdmi,
   s->ths_tdmi = tdmi;
   LIST_INSERT_HEAD(&tdmi->tdmi_subscriptions, s, ths_tdmi_link);
 
-  dvb_fe_tune(tdmi->tdmi_mux, "Full mux subscription");
-
+  dvb_fe_tune(tdmi->tdmi_mux, "Full mux subscription", 99999);
+  abort();
   pthread_mutex_lock(&tda->tda_delivery_mutex);
   streaming_target_connect(&tda->tda_streaming_pad, &s->ths_input);
   pthread_mutex_unlock(&tda->tda_delivery_mutex);
@@ -1209,3 +1242,56 @@ dvb_subscription_create_from_tdmi(th_dvb_mux_instance_t *tdmi,
   notify_reload("subscriptions");
   return s;
 }
+
+
+
+/**
+ *
+ */
+static htsmsg_t *
+dvb_mux_serialize(struct idnode *self, int full)
+{
+  dvb_mux_t *dm = (dvb_mux_t *)self;
+  htsmsg_t *m = htsmsg_create_map();
+  htsmsg_add_str(m, "id", idnode_uuid_as_str(&dm->dm_id));
+
+  char buf[256];
+  dvb_mux_nicename(buf, sizeof(buf), dm);
+
+  htsmsg_add_str(m, "text", buf);
+  return m;
+}
+
+/**
+ *
+ */
+static int
+svcsortcmp(const void *A, const void *B)
+{
+  const service_t *a = *(service_t **)A;
+  const service_t *b = *(service_t **)B;
+  return (int)a->s_dvb_service_id - (int)b->s_dvb_service_id;
+}
+
+
+/**
+ *
+ */
+static idnode_t **
+dvb_mux_get_childs(struct idnode *self)
+{
+  dvb_mux_t *dm = (dvb_mux_t *)self;
+  service_t *s;
+  int cnt = 1;
+
+  LIST_FOREACH(s, &dm->dm_services, s_group_link)
+    cnt++;
+
+  idnode_t **v = malloc(sizeof(idnode_t *) * cnt);
+  cnt = 0;
+  LIST_FOREACH(s, &dm->dm_services, s_group_link)
+    v[cnt++] = (idnode_t *)s;
+  qsort(v, cnt, sizeof(idnode_t *), svcsortcmp);
+  v[cnt] = NULL;
+  return v;
+}
index ed140fdb331c76551310a81d2bd6ae194ac66fee..4bc6d4add9b340049d8889a2fa289082869a40d5 100644 (file)
  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <assert.h>
+
 #include "tvheadend.h"
 #include "packet.h"
 #include "dvb.h"
 #include "epggrab.h"
+#include "settings.h"
+#include "dvb_support.h"
 
 struct dvb_network_list dvb_networks;
 
+static htsmsg_t *dvb_network_serialize(struct idnode *self, int full);
+static idnode_t **dvb_network_get_childs(struct idnode *self);
+
+static const idclass_t dvb_network_class = {
+  .ic_class = "dvbnetwork",
+  .ic_serialize = dvb_network_serialize,
+  .ic_get_childs = dvb_network_get_childs,
+};
+
 /**
  *
  */
 dvb_network_t *
-dvb_network_create(int fe_type)
+dvb_network_create(int fe_type, const char *uuid)
 {
+  printf("Creating network %s\n", uuid);
   dvb_network_t *dn = calloc(1, sizeof(dvb_network_t));
+  if(idnode_insert(&dn->dn_id, uuid, &dvb_network_class)) {
+    free(dn);
+    return NULL;
+  }
+
+  printf("Added network %s\n", idnode_uuid_as_str(&dn->dn_id));
+
   dn->dn_fe_type = fe_type;
-  TAILQ_INIT(&dn->dn_initial_scan_queue);
-  gtimer_arm(&dn->dn_mux_scanner_timer, dvb_network_mux_scanner, dn, 1);
+  TAILQ_INIT(&dn->dn_initial_scan_pending_queue);
+  TAILQ_INIT(&dn->dn_initial_scan_current_queue);
 
   dn->dn_autodiscovery = fe_type != FE_QPSK;
   LIST_INSERT_HEAD(&dvb_networks, dn, dn_global_link);
   return dn;
 }
 
-#if 0
-      htsmsg_get_u32(c, "autodiscovery", &tda->tda_autodiscovery);
-      htsmsg_get_u32(c, "nitoid", &tda->tda_nitoid);
-      htsmsg_get_u32(c, "disable_pmt_monitor", &tda->tda_disable_pmt_monitor);
-#endif
 
-#if 0
+
+/**
+ *
+ */
+static htsmsg_t *
+dvb_network_serialize(struct idnode *self, int full)
+{
+  dvb_network_t *dn = (dvb_network_t *)self;
+  htsmsg_t *m = htsmsg_create_map();
+  htsmsg_add_str(m, "id", idnode_uuid_as_str(&dn->dn_id));
+  htsmsg_add_str(m, "text", idnode_uuid_as_str(&dn->dn_id));
+  return m;
+}
+
+
+/**
+ *
+ */
+static int
+muxsortcmp(const void *A, const void *B)
+{
+  const dvb_mux_t *a = *(dvb_mux_t **)A;
+  const dvb_mux_t *b = *(dvb_mux_t **)B;
+  if(a->dm_conf.dmc_fe_params.frequency < b->dm_conf.dmc_fe_params.frequency)
+    return -1;
+  if(a->dm_conf.dmc_fe_params.frequency > b->dm_conf.dmc_fe_params.frequency)
+    return 1;
+  return a->dm_conf.dmc_polarisation - b->dm_conf.dmc_polarisation;
+}
+
+
+/**
+ *
+ */
+static idnode_t **
+dvb_network_get_childs(struct idnode *self)
+{
+  dvb_network_t *dn = (dvb_network_t *)self;
+  dvb_mux_t *dm;
+  int cnt = 1;
+  LIST_FOREACH(dm, &dn->dn_muxes, dm_network_link)
+    cnt++;
+
+  idnode_t **v = malloc(sizeof(idnode_t *) * cnt);
+  cnt = 0;
+  LIST_FOREACH(dm, &dn->dn_muxes, dm_network_link)
+    v[cnt++] = (idnode_t *)dm;
+  qsort(v, cnt, sizeof(idnode_t *), muxsortcmp);
+  v[cnt] = NULL;
+  return v;
+}
+
+
+/**
+ *
+ */
+static void
+dvb_network_load(htsmsg_t *m, const char *uuid)
+{
+  uint32_t fetype;
+
+  if(htsmsg_get_u32(m, "fetype", &fetype))
+    return;
+
+  dvb_network_t *dn = dvb_network_create(fetype, uuid);
+  if(dn == NULL)
+    return;
+
+  htsmsg_get_u32(m, "autodiscovery",       &dn->dn_autodiscovery);
+  htsmsg_get_u32(m, "nitoid",              &dn->dn_nitoid);
+  htsmsg_get_u32(m, "disable_pmt_monitor", &dn->dn_disable_pmt_monitor);
+
+  dvb_mux_load(dn);
+
+  dvb_network_schedule_initial_scan(dn);
+}
+
+#if 1
 /**
  *
  */
@@ -56,13 +149,18 @@ dvb_network_save(dvb_network_t *dn)
 
   lock_assert(&global_lock);
 
+  htsmsg_add_u32(m, "fetype",              dn->dn_fe_type);
   htsmsg_add_u32(m, "autodiscovery",       dn->dn_autodiscovery);
   htsmsg_add_u32(m, "nitoid",              dn->dn_nitoid);
   htsmsg_add_u32(m, "disable_pmt_monitor", dn->dn_disable_pmt_monitor);
-  abort();
+
+  hts_settings_save(m, "dvb/networks/%s/config",
+                    idnode_uuid_as_str(&dn->dn_id));
+  htsmsg_destroy(m);
 }
 #endif
 
+
 #if 0
 /**
  *
@@ -125,65 +223,82 @@ dvb_network_set_disable_pmt_monitor(th_dvb_network_t *dn, int on)
 #endif
 
 
+
 /**
  *
  */
-void
-dvb_network_mux_scanner(void *aux)
+static void
+dvb_network_initial_scan(void *aux)
 {
   dvb_network_t *dn = aux;
   dvb_mux_t *dm;
 
-  // default period
-  gtimer_arm(&dn->dn_mux_scanner_timer, dvb_network_mux_scanner, dn, 20);
-
-#if 0
-  /* No muxes */
-  if(LIST_FIRST(&dn->dn_mux_instances) == NULL) {
-    dvb_adapter_poweroff(tda);
-    return;
+  while((dm = TAILQ_FIRST(&dn->dn_initial_scan_pending_queue)) != NULL) {
+    assert(dm->dm_scan_status == DM_SCAN_PENDING);
+    if(dvb_fe_tune(dm, "initial scan", 1))
+      break;
+    assert(dm->dm_scan_status == DM_SCAN_CURRENT);
   }
-#endif
-#if 0
-  /* Someone is actively using */
-  if(service_compute_weight(&tda->tda_transports) > 0)
-    return;
-#endif
-#if 0
-  if(tda->tda_mux_current != NULL &&
-     LIST_FIRST(&tda->tda_mux_current->tdmi_subscriptions) != NULL)
-    return; // Someone is doing full mux dump
-#endif
+  gtimer_arm(&dn->dn_initial_scan_timer, dvb_network_initial_scan, dn, 10);
+}
 
-  /* Check if we have muxes pending for quickscan, if so, choose them */
-  if((dm = TAILQ_FIRST(&dn->dn_initial_scan_queue)) != NULL) {
-    dvb_fe_tune(dm, "Initial autoscan");
-    return;
-  }
+/**
+ *
+ */
+void
+dvb_network_schedule_initial_scan(dvb_network_t *dn)
+{
+  gtimer_arm(&dn->dn_initial_scan_timer, dvb_network_initial_scan, dn, 0);
+}
 
-  /* Check EPG */
-  if (dn->dn_mux_epg) {
-    // timeout anything not complete
-    epggrab_mux_stop(dn->dn_mux_epg, 1);
-    dn->dn_mux_epg = NULL; // skip this time
-  } else {
-    dn->dn_mux_epg = epggrab_mux_next(dn);
+/**
+ *
+ */
+void
+dvb_network_init(void)
+{
+  htsmsg_t *l, *c;
+  htsmsg_field_t *f;
+
+  if(0) {
+    dvb_network_save(dvb_network_create(FE_QAM, NULL));
+    exit(0);
   }
 
-  /* EPG */
-  if (dn->dn_mux_epg) {
-    int period = epggrab_mux_period(dn->dn_mux_epg);
-    if (period > 20)
-      gtimer_arm(&dn->dn_mux_scanner_timer,
-                 dvb_network_mux_scanner, dn, period);
-    dvb_fe_tune(dn->dn_mux_epg, "EPG scan");
+  if((l = hts_settings_load_r(1, "dvb/networks")) == NULL)
     return;
 
+
+  htsmsg_print(l);
+
+  HTSMSG_FOREACH(f, l) {
+    if((c = htsmsg_get_map_by_field(f)) == NULL)
+      continue;
+
+    if((c = htsmsg_get_map(c, "config")) == NULL)
+      continue;
+
+    dvb_network_load(c, f->hmf_name);
   }
+  htsmsg_destroy(l);
+}
 
-#if 0
-  /* Ensure we stop current mux and power off (if required) */
-  if (tda->tda_mux_current)
-    dvb_fe_stop(tda->tda_mux_current, 0);
-#endif
+
+/**
+ *
+ */
+idnode_t **
+dvb_network_root(void)
+{
+  dvb_network_t *dn;
+  int cnt = 1;
+  LIST_FOREACH(dn, &dvb_networks, dn_global_link)
+    cnt++;
+
+  idnode_t **v = malloc(sizeof(idnode_t *) * cnt);
+  cnt = 0;
+  LIST_FOREACH(dn, &dvb_networks, dn_global_link)
+    v[cnt++] = &dn->dn_id;
+  v[cnt] = NULL;
+  return v;
 }
index e771d898f3ee9438f8786a79b65b02a2f74b63fb..109312e2c4b26dce067c3bb269aa4550f00ae7c9 100644 (file)
 #include "dvb_support.h"
 #include "notify.h"
 
-
-
-/**
- *
- */
-
-
-
-
+static htsmsg_t *dvb_service_serialize(service_t *s, int full);
 
 
 /**
@@ -110,7 +102,7 @@ dvb_service_start(service_t *t, unsigned int weight, int force_start)
 
   return r;
 #endif
-  return SM_CODE_NO_HW_ATTACHED;
+  return SM_CODE_NO_FREE_ADAPTER;
 }
 
 
@@ -193,7 +185,7 @@ dvb_service_save(service_t *t)
   dvb_mux_t *dm = t->s_dvb_mux;
 
   hts_settings_save(m, "dvb/networks/%s/muxes/%s/services/%04x",
-                    dm->dm_dn->dn_uuid,
+                    idnode_uuid_as_str(&dm->dm_dn->dn_id),
                     dm->dm_local_identifier,
                     t->s_dvb_service_id);
 
@@ -217,7 +209,8 @@ dvb_service_load(dvb_mux_t *dm)
   lock_assert(&global_lock);
 
   l = hts_settings_load("dvb/networks/%s/muxes/%s/services",
-                        dm->dm_dn->dn_uuid, dm->dm_local_identifier);
+                        idnode_uuid_as_str(&dm->dm_dn->dn_id),
+                        dm->dm_local_identifier);
   if(l == NULL)
     return;
 
@@ -398,6 +391,7 @@ dvb_service_find2(dvb_mux_t *dm, uint16_t sid, int pmt_pid,
   t->s_config_save   = dvb_service_save;
   t->s_setsourceinfo = dvb_service_setsourceinfo;
   t->s_grace_period  = dvb_grace_period;
+  t->s_serialize     = dvb_service_serialize;
 
   t->s_dvb_mux = dm;
   LIST_INSERT_HEAD(&dm->dm_services, t, s_group_link);
@@ -412,38 +406,44 @@ dvb_service_find2(dvb_mux_t *dm, uint16_t sid, int pmt_pid,
 /**
  *
  */
-htsmsg_t *
-dvb_service_build_msg(service_t *t)
+static htsmsg_t *
+dvb_service_serialize(service_t *s, int full)
 {
-  dvb_mux_t *dm = t->s_dvb_mux;
+  dvb_mux_t *dm = s->s_dvb_mux;
   htsmsg_t *m = htsmsg_create_map();
   char buf[100];
-  htsmsg_add_str(m, "uuid", t->s_uuid);
-  htsmsg_add_u32(m, "enabled", t->s_enabled);
-  htsmsg_add_u32(m, "channel", t->s_channel_number);
 
-  htsmsg_add_u32(m, "sid", t->s_dvb_service_id);
-  htsmsg_add_u32(m, "pmt", t->s_pmt_pid);
-  htsmsg_add_u32(m, "pcr", t->s_pcr_pid);
-  
-  htsmsg_add_str(m, "type", service_servicetype_txt(t));
+  htsmsg_add_str(m, "id", idnode_uuid_as_str(&s->s_id));
+
+  snprintf(buf, sizeof(buf), "%s (0x%04x)",
+           s->s_svcname ?: "<noname>", s->s_dvb_service_id);
+  htsmsg_add_str(m, "text", buf);
+
+
+  htsmsg_add_u32(m, "enabled", s->s_enabled);
+  htsmsg_add_u32(m, "channel", s->s_channel_number);
+
+  htsmsg_add_u32(m, "sid", s->s_dvb_service_id);
+  htsmsg_add_u32(m, "pmt", s->s_pmt_pid);
+  htsmsg_add_u32(m, "pcr", s->s_pcr_pid);
 
-  htsmsg_add_str(m, "svcname", t->s_svcname ?: "");
-  htsmsg_add_str(m, "provider", t->s_provider ?: "");
+  htsmsg_add_str(m, "type", service_servicetype_txt(s));
+
+  htsmsg_add_str(m, "svcname", s->s_svcname ?: "");
+  htsmsg_add_str(m, "provider", s->s_provider ?: "");
 
   htsmsg_add_str(m, "network", dm->dm_network_name ?: "");
 
   dvb_mux_nicefreq(buf, sizeof(buf), dm);
   htsmsg_add_str(m, "mux", buf);
 
-  if(t->s_ch != NULL)
-    htsmsg_add_str(m, "channelname", t->s_ch->ch_name);
+  if(s->s_ch != NULL)
+    htsmsg_add_str(m, "channelname", s->s_ch->ch_name);
 
-  if(t->s_dvb_charset != NULL)
-    htsmsg_add_str(m, "dvb_charset", t->s_dvb_charset);
+  if(s->s_dvb_charset != NULL)
+    htsmsg_add_str(m, "dvb_charset", s->s_dvb_charset);
 
-  htsmsg_add_u32(m, "dvb_eit_enable", t->s_dvb_eit_enable);
+  htsmsg_add_u32(m, "dvb_eit_enable", s->s_dvb_eit_enable);
 
   return m;
 }
index 6cd5e4515c8e1902484b4e195b5b3e65467c4e8a..3537cb5140118b02c4f03ff1f2da23e29a06af0e 100644 (file)
@@ -52,25 +52,21 @@ dvb_table_fastswitch(th_dvb_mux_instance_t *tdmi)
   th_dvb_table_t *tdt;
   th_dvb_adapter_t *tda = tdmi->tdmi_adapter;
   dvb_mux_t *dm = tdmi->tdmi_mux;
-  dvb_network_t *dn = dm->dm_dn;
   char buf[100];
 
-  if(!dm->dm_table_initial)
+  if(dm->dm_scan_status == DM_SCAN_DONE)
     return;
 
   LIST_FOREACH(tdt, &dm->dm_tables, tdt_link)
     if((tdt->tdt_flags & TDT_QUICKREQ) && tdt->tdt_count == 0)
       return;
 
-  dm->dm_table_initial = 0;
-  dn->dn_initial_num_mux--;
   dvb_mux_save(dm);
 
-
   dvb_mux_nicename(buf, sizeof(buf), dm);
   tvhlog(LOG_DEBUG, "dvb", "\"%s\" initial scan completed for \"%s\"",
         tda->tda_rootpath, buf);
-  dvb_network_mux_scanner(dn);
+  dvb_mux_initial_scan_done(dm);
 }
 
 
index b02e17fc02b5c12c6b81bdde1711feaf6d26dd71..85490585d591dfdfee7a43badd892b4f5d8e4cae 100644 (file)
@@ -369,13 +369,14 @@ void epggrab_ota_complete  ( epggrab_ota_mux_t *ota )
     TAILQ_FOREACH(ota, &dm->dm_epg_grab, dm_link) {
       if (ota->is_reg && ota->state == EPGGRAB_OTA_MUX_RUNNING) break;
     }
-
+#if 0  // XXX(dvbreorg)
     /* All complete (bring timer forward) */
     if (!ota) {
       dvb_network_t *dn = dm->dm_dn;
       gtimer_arm(&dn->dn_mux_scanner_timer,
                  dvb_network_mux_scanner, dn, 20);
     }
+#endif
   }
 }
 
index 82450a377f5644d4993c35cbbc4c76d8e0e34774..d2b7451528dba2655baddc3228ddcb2adc4b9038 100644 (file)
@@ -305,7 +305,7 @@ int fb_scandir ( const char *path, fb_dirent ***list )
       for (i = 0; i < ret; i++) {
         (*list)[i] = calloc(1, sizeof(fb_dirent));
         strcpy((*list)[i]->name, de[i]->d_name);
-        (*list)[i]->type = FB_DIRECT;
+        (*list)[i]->type = de[i]->d_type == DT_DIR ? FB_DIR : FB_FILE;
         free(de[i]);
       }
       free(de);
diff --git a/src/idnode.c b/src/idnode.c
new file mode 100644 (file)
index 0000000..58b3bbd
--- /dev/null
@@ -0,0 +1,158 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "idnode.h"
+
+static int randfd = 0;
+
+RB_HEAD(idnode_tree, idnode);
+
+static struct idnode_tree idnodes;
+
+/**
+ *
+ */
+static int
+hexnibble(char c)
+{
+  switch(c) {
+  case '0' ... '9':    return c - '0';
+  case 'a' ... 'f':    return c - 'a' + 10;
+  case 'A' ... 'F':    return c - 'A' + 10;
+  default:
+    return -1;
+  }
+}
+
+
+/**
+ *
+ */
+static int
+hex2bin(uint8_t *buf, size_t buflen, const char *str)
+{
+  int hi, lo;
+
+  while(*str) {
+    if(buflen == 0)
+      return -1;
+    if((hi = hexnibble(*str++)) == -1)
+      return -1;
+    if((lo = hexnibble(*str++)) == -1)
+      return -1;
+
+    *buf++ = hi << 4 | lo;
+    buflen--;
+  }
+  return 0;
+}
+
+
+/**
+ *
+ */
+static void
+bin2hex(char *dst, size_t dstlen, const uint8_t *src, size_t srclen)
+{
+  while(dstlen > 2 && srclen > 0) {
+    *dst++ = "0123456789abcdef"[*src >> 4];
+    *dst++ = "0123456789abcdef"[*src & 0xf];
+    src++;
+    srclen--;
+    dstlen -= 2;
+  }
+  *dst = 0;
+}
+
+
+/**
+ *
+ */
+void
+idnode_init(void)
+{
+  randfd = open("/dev/urandom", O_RDONLY);
+  if(randfd == -1)
+    exit(1);
+}
+
+
+/**
+ *
+ */
+static int
+in_cmp(const idnode_t *a, const idnode_t *b)
+{
+  return memcmp(a->in_uuid, b->in_uuid, 16);
+}
+
+
+/**
+ *
+ */
+int
+idnode_insert(idnode_t *in, const char *uuid, const idclass_t *class)
+{
+  idnode_t *c;
+  if(uuid == NULL) {
+    if(read(randfd, in->in_uuid, 16) != 16) {
+      perror("read(random for uuid)");
+      exit(1);
+    }
+  } else {
+    if(hex2bin(in->in_uuid, 16, uuid))
+      return -1;
+  }
+
+  in->in_class = class;
+
+  c = RB_INSERT_SORTED(&idnodes, in, in_link, in_cmp);
+  if(c != NULL) {
+    fprintf(stderr, "Id node collision\n");
+    abort();
+  }
+  return 0;
+}
+
+
+/**
+ *
+ */
+const char *
+idnode_uuid_as_str(const idnode_t *in)
+{
+  static char ret[16][33];
+  static int p;
+  char *b = ret[p];
+  bin2hex(b, 33, in->in_uuid, 16);
+  p = (p + 1) & 15;
+  return b;
+}
+
+
+/**
+ *
+ */
+idnode_t *
+idnode_find(const char *uuid)
+{
+  idnode_t skel, *r;
+
+  if(hex2bin(skel.in_uuid, 16, uuid))
+    return NULL;
+  r = RB_FIND(&idnodes, &skel, in_link, in_cmp);
+  return r;
+}
+
+
+/**
+ *
+ */
+void
+idnode_unlink(idnode_t *in)
+{
+  RB_REMOVE(&idnodes, in, in_link);
+}
diff --git a/src/idnode.h b/src/idnode.h
new file mode 100644 (file)
index 0000000..a49b438
--- /dev/null
@@ -0,0 +1,29 @@
+#pragma once
+
+#include "tvheadend.h"
+
+struct htsmsg;
+struct idnode;
+
+typedef struct idclass {
+  const char *ic_class;
+  struct htsmsg *(*ic_serialize)(struct idnode *self, int full);
+  struct idnode **(*ic_get_childs)(struct idnode *self);
+} idclass_t;
+
+
+typedef struct idnode {
+  uint8_t in_uuid[16];
+  RB_ENTRY(idnode) in_link;
+  const idclass_t *in_class;
+} idnode_t;
+
+void idnode_init(void);
+
+int idnode_insert(idnode_t *in, const char *uuid, const idclass_t *class);
+
+const char *idnode_uuid_as_str(const idnode_t *in);
+
+idnode_t *idnode_find(const char *uuid);
+
+void idnode_unlink(idnode_t *in);
index 8705e71da84a895630f068162feeff398843570f..5abc4ef38d85050243e45145c05c8a921c95d0c7 100644 (file)
@@ -227,7 +227,7 @@ iptv_service_start(service_t *t, unsigned int weight, int force_start)
     fd = tvh_socket(AF_INET6, SOCK_DGRAM, 0);
   }
   if(fd == -1) {
-    tvhlog(LOG_ERR, "IPTV", "\"%s\" cannot open socket", t->s_uuid);
+    tvhlog(LOG_ERR, "IPTV", "\"%s\" cannot open socket", t->s_nicename);
     return -1;
   }
 
@@ -237,7 +237,7 @@ iptv_service_start(service_t *t, unsigned int weight, int force_start)
   ifr.ifr_name[IFNAMSIZ - 1] = 0;
   if(ioctl(fd, SIOCGIFINDEX, &ifr)) {
     tvhlog(LOG_ERR, "IPTV", "\"%s\" cannot find interface %s", 
-          t->s_uuid, t->s_iptv_iface);
+          t->s_nicename, t->s_iptv_iface);
     close(fd);
     return -1;
   }
@@ -251,7 +251,7 @@ iptv_service_start(service_t *t, unsigned int weight, int force_start)
     setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &m, sizeof(struct ip_mreqn));
     if(bind(fd, (struct sockaddr *)&sin, sizeof(sin)) == -1) {
       tvhlog(LOG_ERR, "IPTV", "\"%s\" cannot bind %s:%d -- %s",
-           t->s_uuid, inet_ntoa(sin.sin_addr), t->s_iptv_port,
+           t->s_nicename, inet_ntoa(sin.sin_addr), t->s_iptv_port,
            strerror(errno));
       close(fd);
       return -1;
@@ -265,7 +265,7 @@ iptv_service_start(service_t *t, unsigned int weight, int force_start)
       if(setsockopt(fd, SOL_IP, IP_ADD_MEMBERSHIP, &m,
                 sizeof(struct ip_mreqn)) == -1) {
       tvhlog(LOG_ERR, "IPTV", "\"%s\" cannot join %s -- %s",
-           t->s_uuid, inet_ntoa(m.imr_multiaddr), strerror(errno));
+           t->s_nicename, inet_ntoa(m.imr_multiaddr), strerror(errno));
       close(fd);
       return -1;
     }
@@ -279,7 +279,7 @@ iptv_service_start(service_t *t, unsigned int weight, int force_start)
     if(bind(fd, (struct sockaddr *)&sin6, sizeof(sin6)) == -1) {
       inet_ntop(AF_INET6, &sin6.sin6_addr, straddr, sizeof(straddr));
       tvhlog(LOG_ERR, "IPTV", "\"%s\" cannot bind %s:%d -- %s",
-           t->s_uuid, straddr, t->s_iptv_port,
+           t->s_nicename, straddr, t->s_iptv_port,
            strerror(errno));
       close(fd);
       return -1;
@@ -294,7 +294,7 @@ iptv_service_start(service_t *t, unsigned int weight, int force_start)
       inet_ntop(AF_INET6, m6.ipv6mr_multiaddr.s6_addr,
                straddr, sizeof(straddr));
       tvhlog(LOG_ERR, "IPTV", "\"%s\" cannot join %s -- %s",
-           t->s_uuid, straddr, strerror(errno));
+           t->s_nicename, straddr, strerror(errno));
       close(fd);
       return -1;
     }
@@ -312,7 +312,7 @@ iptv_service_start(service_t *t, unsigned int weight, int force_start)
   ev.data.fd = fd;
   if(epoll_ctl(iptv_epollfd, EPOLL_CTL_ADD, fd, &ev) == -1) {
     tvhlog(LOG_ERR, "IPTV", "\"%s\" cannot add to epoll set -- %s", 
-          t->s_uuid, strerror(errno));
+          t->s_nicename, strerror(errno));
     close(fd);
     return -1;
   }
@@ -356,7 +356,7 @@ iptv_service_stop(service_t *t)
   ifr.ifr_name[IFNAMSIZ - 1] = 0;
   if(ioctl(t->s_iptv_fd, SIOCGIFINDEX, &ifr)) {
     tvhlog(LOG_ERR, "IPTV", "\"%s\" cannot find interface %s",
-          t->s_uuid, t->s_iptv_iface);
+          t->s_nicename, t->s_iptv_iface);
   }
 
   if(t->s_iptv_group.s_addr != 0) {
@@ -371,7 +371,7 @@ iptv_service_stop(service_t *t)
     if(setsockopt(t->s_iptv_fd, SOL_IP, IP_DROP_MEMBERSHIP, &m,
                  sizeof(struct ip_mreqn)) == -1) {
       tvhlog(LOG_ERR, "IPTV", "\"%s\" cannot leave %s -- %s",
-            t->s_uuid, inet_ntoa(m.imr_multiaddr), strerror(errno));
+            t->s_nicename, inet_ntoa(m.imr_multiaddr), strerror(errno));
     }
   } else {
     char straddr[INET6_ADDRSTRLEN];
@@ -388,7 +388,7 @@ iptv_service_stop(service_t *t)
                straddr, sizeof(straddr));
 
       tvhlog(LOG_ERR, "IPTV", "\"%s\" cannot leave %s -- %s",
-            t->s_uuid, straddr, strerror(errno));
+            t->s_nicename, straddr, strerror(errno));
     }
 
 
@@ -440,8 +440,9 @@ iptv_service_save(service_t *t)
   psi_save_service_settings(m, t);
   pthread_mutex_unlock(&t->s_stream_mutex);
   
-  hts_settings_save(m, "iptvservices/%s",
-                   t->s_uuid);
+  abort(); // XXX(dvbreorg);
+
+  //  hts_settings_save(m, "iptvservices/%s", t->s_uuid);
 
   htsmsg_destroy(m);
 }
@@ -484,7 +485,8 @@ iptv_grace_period(service_t *t)
 static void
 iptv_service_dtor(service_t *t)
 {
-  hts_settings_remove("iptvservices/%s", t->s_uuid); 
+  abort(); // XXX(dvbreorg);
+  //  hts_settings_remove("iptvservices/%s", t->s_uuid); 
 }
 
 
@@ -504,7 +506,7 @@ iptv_service_find(const char *id, int create)
       return NULL;
 
     LIST_FOREACH(t, &iptv_all_services, s_group_link)
-      if(!strcmp(t->s_uuid, id))
+      if(!strcmp(t->s_nicename, id)) // XXX(dvbreorg)
        return t;
   }
 
index 580a151cf97a2a11e76d622cf40381eb676d852d..5e93b94e9722dc5466c1021dac4de14a0da11b60 100644 (file)
@@ -60,6 +60,7 @@
 #include "ffdecsa/FFdecsa.h"
 #include "muxes.h"
 #include "config2.h"
+#include "idnode.h"
 
 int running;
 time_t dispatch_clock;
@@ -444,6 +445,9 @@ main(int argc, char **argv)
   access_init(createdefault);
 
   tcp_server_init();
+
+  idnode_init();
+
 #if ENABLE_LINUXDVB
   dvb_init(adapter_mask, dvb_rawts_input);
 #endif
index 90b8a4d72245339e7bcdb9bcb4c1f642ee03e9b0..c625148d98aed61b9fb6e998319f2d538920f070 100644 (file)
 #include "htsp_server.h"
 #include "lang_codes.h"
 
-#define SERVICE_HASH_WIDTH 101
+static void service_data_timeout(void *aux);
 
-static struct service_list servicehash[SERVICE_HASH_WIDTH];
+static htsmsg_t *service_serialize(struct idnode *self, int full);
 
-static void service_data_timeout(void *aux);
+static const idclass_t service_class = {
+  .ic_class = "service",
+  .ic_serialize = service_serialize,
+};
 
 /**
  *
@@ -391,14 +394,14 @@ service_destroy(service_t *t)
   }
 
   LIST_REMOVE(t, s_group_link);
-  LIST_REMOVE(t, s_hash_link);
-  
+
+  idnode_unlink(&t->s_id);
+
   if(t->s_status != SERVICE_IDLE)
     service_stop(t);
 
   t->s_status = SERVICE_ZOMBIE;
 
-  free(t->s_uuid);
   free(t->s_svcname);
   free(t->s_provider);
   free(t->s_dvb_charset);
@@ -429,14 +432,12 @@ service_destroy(service_t *t)
 service_t *
 service_create(const char *uuid, int source_type)
 {
-  unsigned int hash = tvh_strhash(uuid, SERVICE_HASH_WIDTH);
   service_t *t = calloc(1, sizeof(service_t));
 
   lock_assert(&global_lock);
 
   pthread_mutex_init(&t->s_stream_mutex, NULL);
   pthread_cond_init(&t->s_tss_cond, NULL);
-  t->s_uuid = strdup(uuid);
   t->s_source_type = source_type;
   t->s_refcount = 1;
   t->s_enabled = 1;
@@ -449,7 +450,8 @@ service_create(const char *uuid, int source_type)
 
   streaming_pad_init(&t->s_streaming_pad);
 
-  LIST_INSERT_HEAD(&servicehash[hash], t, s_hash_link);
+  idnode_insert(&t->s_id, uuid, &service_class);
+
   return t;
 }
 
@@ -459,15 +461,8 @@ service_create(const char *uuid, int source_type)
 service_t *
 service_find_by_identifier(const char *identifier)
 {
-  service_t *t;
-  unsigned int hash = tvh_strhash(identifier, SERVICE_HASH_WIDTH);
-
-  lock_assert(&global_lock);
-
-  LIST_FOREACH(t, &servicehash[hash], s_hash_link)
-    if(!strcmp(t->s_uuid, identifier))
-      break;
-  return t;
+  idnode_t *id = idnode_find(identifier);
+  return id->in_class == &service_class ? (service_t *)id : NULL;
 }
 
 
@@ -1128,3 +1123,14 @@ htsmsg_t *servicetype_list ( void )
   }
   return ret;
 }
+
+
+/**
+ *
+ */
+static htsmsg_t *
+service_serialize(struct idnode *self, int full)
+{
+  service_t *s = (service_t *)self;
+  return s->s_serialize(s, full);
+}
index e63dfbfff0d5d1b8604c2dd1ad3d280316d334cb..294ef695ebdfe1f307c4f419b333adb0a997be42 100644 (file)
@@ -22,7 +22,7 @@
 #define PID_TELETEXT_BASE 0x2000
 
 #include "htsmsg.h"
-
+#include "idnode.h"
 
 
 /**
@@ -201,8 +201,7 @@ service_start_cand_t *service_find_cand(struct service_start_cand_list *sscl,
  *
  */
 typedef struct service {
-
-  LIST_ENTRY(service) s_hash_link;
+  idnode_t s_id;
 
   enum {
     /**
@@ -305,16 +304,13 @@ typedef struct service {
 
   void (*s_dtor)(struct service *t);
 
+  htsmsg_t *(*s_serialize)(struct service *s, int full);
+
   /*
    * Per source type structs
    */
   struct dvb_mux *s_dvb_mux;
 
-  /**
-   * Unique identifer
-   */
-  char *s_uuid;
-
   /**
    * Name usable for displaying to user
    */
index bf1614f8827485803ec7881222973743bfc9e1a2..7a490f53606461f9488e9f2af30b9e1c9007d01a 100755 (executable)
@@ -401,8 +401,8 @@ streaming_code2txt(int code)
   case SM_CODE_SUBSCRIPTION_OVERRIDDEN:
     return "Subscription overridden";
 
-  case SM_CODE_NO_HW_ATTACHED:
-    return "No hardware present";
+  case SM_CODE_NO_FREE_ADAPTER:
+    return "No free adapter";
   case SM_CODE_MUX_NOT_ENABLED:
     return "Mux not enabled";
   case SM_CODE_NOT_FREE:
index e401d58245a937a37dbe715058875b7204f4b961..6fddae3bb6e42237dc8c402acdbe8afff8369603 100644 (file)
@@ -284,7 +284,7 @@ typedef enum {
 #define SM_CODE_SOURCE_DELETED            102
 #define SM_CODE_SUBSCRIPTION_OVERRIDDEN   103
 
-#define SM_CODE_NO_HW_ATTACHED            200
+#define SM_CODE_NO_FREE_ADAPTER           200
 #define SM_CODE_MUX_NOT_ENABLED           201
 #define SM_CODE_NOT_FREE                  202
 #define SM_CODE_TUNING_FAILED             203
index 98d124262cc3dc53cb9616d53e2ca6a4f6096cb7..841840b84f5857a9ccc30b58739141a48eefb552 100644 (file)
@@ -1669,7 +1669,7 @@ build_record_iptv(service_t *t)
   htsmsg_t *r = htsmsg_create_map();
   char abuf[INET_ADDRSTRLEN];
   char abuf6[INET6_ADDRSTRLEN];
-  htsmsg_add_str(r, "id", t->s_uuid);
+  //  htsmsg_add_str(r, "id", t->s_uuid); // XXX(dvbreorg)
 
   htsmsg_add_str(r, "channelname", t->s_ch ? t->s_ch->ch_name : "");
   htsmsg_add_str(r, "interface", t->s_iptv_iface ?: "");
@@ -1828,7 +1828,7 @@ extjs_tvadapter(http_connection_t *hc, const char *remain, void *opaque)
   array = htsmsg_create_list();
 
 #if ENABLE_LINUXDVB
-  //  extjs_list_dvb_adapters(array);
+  extjs_list_dvb_adapters(array);
 #endif
 
 #if ENABLE_V4L
index c6aebc41d5e232082c2e14498ac8888563d675a3..f321200ae4f480bfeb64def88af1a4ccec1c7eb9 100644 (file)
@@ -43,7 +43,6 @@
 #include "dvb/dvb_preconf.h"
 #include "dvr/dvr.h"
 
-#if 0
 
 
 
@@ -61,7 +60,7 @@ extjs_dvblocations(http_connection_t *hc, const char *remain, void *opaque)
 
   if(s == NULL || a == NULL)
     return HTTP_STATUS_BAD_REQUEST;
-  
+
   pthread_mutex_lock(&global_lock);
 
   if(http_access_verify(hc, ACCESS_ADMIN)) {
@@ -85,6 +84,7 @@ extjs_dvblocations(http_connection_t *hc, const char *remain, void *opaque)
   return 0;
 }
 
+
 /**
  *
  */
@@ -115,8 +115,6 @@ extjs_dvbadapter(http_connection_t *hc, const char *remain, void *opaque)
   const char *op = http_arg_get(&hc->hc_req_args, "op");
   const char *sibling = http_arg_get(&hc->hc_req_args, "sibling");
   const char *s;
-  th_dvb_mux_instance_t *tdmi;
-  service_t *t;
 
   pthread_mutex_lock(&global_lock);
 
@@ -151,15 +149,12 @@ extjs_dvbadapter(http_connection_t *hc, const char *remain, void *opaque)
     htsmsg_add_str(r, "id", tda->tda_identifier);
     htsmsg_add_str(r, "device", tda->tda_rootpath ?: "No hardware attached");
     htsmsg_add_str(r, "name", tda->tda_displayname);
-    htsmsg_add_u32(r, "automux", tda->tda_autodiscovery);
     htsmsg_add_u32(r, "skip_initialscan", tda->tda_skip_initialscan);
     htsmsg_add_u32(r, "idleclose", tda->tda_idleclose);
     htsmsg_add_u32(r, "skip_checksubscr", tda->tda_skip_checksubscr);
     htsmsg_add_u32(r, "qmon", tda->tda_qmon);
     htsmsg_add_u32(r, "poweroff", tda->tda_poweroff);
     htsmsg_add_u32(r, "sidtochan", tda->tda_sidtochan);
-    htsmsg_add_u32(r, "nitoid", tda->tda_nitoid);
-    htsmsg_add_u32(r, "disable_pmt_monitor", tda->tda_disable_pmt_monitor);
     htsmsg_add_u32(r, "full_mux_rx", tda->tda_full_mux_rx+1);
     htsmsg_add_str(r, "diseqcversion", 
                   ((const char *[]){"DiSEqC 1.0 / 2.0",
@@ -176,9 +171,6 @@ extjs_dvbadapter(http_connection_t *hc, const char *remain, void *opaque)
     if((s = http_arg_get(&hc->hc_req_args, "name")) != NULL)
       dvb_adapter_set_displayname(tda, s);
 
-    s = http_arg_get(&hc->hc_req_args, "automux");
-    dvb_adapter_set_auto_discovery(tda, !!s);
-
     s = http_arg_get(&hc->hc_req_args, "skip_initialscan");
     dvb_adapter_set_skip_initialscan(tda, !!s);
 
@@ -197,15 +189,9 @@ extjs_dvbadapter(http_connection_t *hc, const char *remain, void *opaque)
     s = http_arg_get(&hc->hc_req_args, "sidtochan");
     dvb_adapter_set_sidtochan(tda, !!s);
 
-    s = http_arg_get(&hc->hc_req_args, "disable_pmt_monitor");
-    dvb_adapter_set_disable_pmt_monitor(tda, !!s);
-
     s = http_arg_get(&hc->hc_req_args, "full_mux_rx");
     dvb_adapter_set_full_mux_rx(tda, atoi(s)-1);
 
-    if((s = http_arg_get(&hc->hc_req_args, "nitoid")) != NULL)
-      dvb_adapter_set_nitoid(tda, atoi(s));
-
     if((s = http_arg_get(&hc->hc_req_args, "diseqcversion")) != NULL) {
       if(!strcmp(s, "DiSEqC 1.0 / 2.0"))
        dvb_adapter_set_diseqc_version(tda, 0);
@@ -231,11 +217,11 @@ extjs_dvbadapter(http_connection_t *hc, const char *remain, void *opaque)
 //    sc = http_arg_get(&hc->hc_req_args, "satconf");
 
     if((s = http_arg_get(&hc->hc_req_args, "network")) != NULL)
-      dvb_mux_preconf_add_network(tda, s);
+      dvb_mux_preconf_add_network(tda->tda_dn, s);
 
     out = htsmsg_create_map();
     htsmsg_add_u32(out, "success", 1);
-
+#if 0
   } else if(!strcmp(op, "serviceprobe")) {
 
     tvhlog(LOG_NOTICE, "web interface",
@@ -251,6 +237,7 @@ extjs_dvbadapter(http_connection_t *hc, const char *remain, void *opaque)
 
     out = htsmsg_create_map();
     htsmsg_add_u32(out, "success", 1);
+#endif
 
   } else {
     pthread_mutex_unlock(&global_lock);
@@ -265,6 +252,7 @@ extjs_dvbadapter(http_connection_t *hc, const char *remain, void *opaque)
   return 0;  
 }
 
+#if 0
 
 /**
  *
@@ -678,6 +666,8 @@ extjs_dvb_copymux(http_connection_t *hc, const char *remain, void *opaque)
 }
 #endif
 
+#endif
+
 /**
  *
  */
@@ -689,7 +679,6 @@ extjs_list_dvb_adapters(htsmsg_t *array)
     htsmsg_add_msg(array, NULL, dvb_adapter_build_msg(tda));
 }
 
-#endif
 
 /**
  *
@@ -711,27 +700,29 @@ extjs_dvbnetworks(http_connection_t *hc, const char *remain, void *opaque)
     return HTTP_STATUS_UNAUTHORIZED;
   }
 
-  printf("s=%s\n", s);
-
   out = htsmsg_create_list();
+  idnode_t **v;
+
   if(!strcmp(s, "root")) {
-      htsmsg_t *n = htsmsg_create_map();
-      htsmsg_add_str(n, "text", "Network1");
-      htsmsg_add_str(n, "id", "net/1");
-      htsmsg_add_str(n, "cls", "folder");
-      htsmsg_add_str(n, "iconCls", "iptv");
-      htsmsg_add_msg(out, NULL, n);
-
-      n = htsmsg_create_map();
-      htsmsg_add_str(n, "text", "Network2");
-      htsmsg_add_str(n, "id", "net/2");
-      htsmsg_add_str(n, "cls", "folder");
-      htsmsg_add_msg(out, NULL, n);
+    v = dvb_network_root();
+  } else {
+    idnode_t *n = idnode_find(s);
+    v = n != NULL && n->in_class->ic_get_childs != NULL ? 
+      n->in_class->ic_get_childs(n) : NULL;
   }
 
+  int i;
+  for(i = 0; v[i] != NULL; i++) {
+    htsmsg_t *m = v[i]->in_class->ic_serialize(v[i], 0);
+    if(v[i]->in_class->ic_get_childs == NULL)
+      htsmsg_add_u32(m, "leaf", 1);
+    htsmsg_add_msg(out, NULL, m);
+  }
 
   pthread_mutex_unlock(&global_lock);
 
+  free(v);
+
   htsmsg_json_serialize(out, hq, 0);
   htsmsg_destroy(out);
   http_output_content(hc, "text/x-json; charset=UTF-8");
@@ -748,14 +739,14 @@ extjs_start_dvb(void)
 {
   http_path_add("/dvb/networks", 
                NULL, extjs_dvbnetworks, ACCESS_WEB_INTERFACE);
-#if 0
   http_path_add("/dvb/locations", 
                NULL, extjs_dvblocations, ACCESS_WEB_INTERFACE);
 
-
   http_path_add("/dvb/adapter", 
                NULL, extjs_dvbadapter, ACCESS_ADMIN);
 
+#if 0
+
   http_path_add("/dvb/muxes", 
                NULL, extjs_dvbmuxes, ACCESS_ADMIN);
 
diff --git a/src/webui/static/app/dvb_networks.js b/src/webui/static/app/dvb_networks.js
new file mode 100644 (file)
index 0000000..44b6868
--- /dev/null
@@ -0,0 +1,25 @@
+/**
+ *
+ */
+tvheadend.dvb_networks = function() {
+
+  var loader = new Ext.tree.TreeLoader({
+    dataUrl: 'dvb/networks'
+  });
+
+  var tree = new Ext.tree.TreePanel({
+    title: 'DVB Networks',
+    loader: loader,
+    root : new Ext.tree.AsyncTreeNode({
+      id : 'root',
+      text: 'DVB Networks'
+    })
+  });
+
+
+  tree.on('render', function() {
+    tree.getRootNode().expand();
+  });
+
+  return tree;
+}
index f72a865dccf72447e8677f1322fc272ba6db363a..be97063f14ff50475b7b9f6a7d2e314df284358f 100644 (file)
@@ -606,7 +606,7 @@ http_stream_tdmi(http_connection_t *hc, th_dvb_mux_instance_t *tdmi)
   streaming_queue_init(&sq, SMT_PACKET);
 
   s = dvb_subscription_create_from_tdmi(tdmi, "HTTP", &sq.sq_st);
-  name = strdupa(tdmi->tdmi_mux->dm_uuid);
+  name = "foo"; // strdupa(tdmi->tdmi_mux->dm_uuid);  XXX(dvbreorg)
   pthread_mutex_unlock(&global_lock);
   http_stream_run(hc, &sq, name, MC_PASS);
   pthread_mutex_lock(&global_lock);