]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
wizard: implement tuner / network type dialog
authorJaroslav Kysela <perex@perex.cz>
Fri, 15 Jan 2016 20:58:18 +0000 (21:58 +0100)
committerJaroslav Kysela <perex@perex.cz>
Tue, 19 Jan 2016 14:14:15 +0000 (15:14 +0100)
12 files changed:
src/api/api_wizard.c
src/htsmsg.c
src/input.h
src/input/mpegts.h
src/input/mpegts/mpegts_network.c
src/input/mpegts/mpegts_service.c
src/input/mpegts/satip/satip_frontend.c
src/input/mpegts/satip/satip_private.h
src/input/mpegts/satip/satip_satconf.c
src/queue.h
src/wizard.c
src/wizard.h

index 3d0aa6994464518ce155ebd68b6e68fd1057219c..785fd3dae22bbf16eaf58dbe485eb8dfffe0dcd8 100644 (file)
 #include "config.h"
 #include "wizard.h"
 
+static int
+wizard_page ( const char *page )
+{
+  pthread_mutex_lock(&global_lock);
+  if (strcmp(page, config.wizard ?: "")) {
+    free(config.wizard);
+    config.wizard = page[0] ? strdup(page) : NULL;
+    config_save();
+  }
+  pthread_mutex_unlock(&global_lock);
+  return 0;
+}
+
 static int
 wizard_idnode_load_simple
   ( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
 {
   int r;
   wizard_build_fcn_t fcn = opaque;
-  wizard_page_t *page = fcn();
+  wizard_page_t *page = fcn(perm->aa_lang_ui);
   r = api_idnode_load_simple(perm, &page->idnode, op, args, resp);
+  wizard_page(page->name);
   page->free(page);
   return r;
 }
@@ -42,36 +56,24 @@ wizard_idnode_save_simple
 {
   int r;
   wizard_build_fcn_t fcn = opaque;
-  wizard_page_t *page = fcn();
+  wizard_page_t *page = fcn(perm->aa_lang_ui);
   r = api_idnode_save_simple(perm, &page->idnode, op, args, resp);
   page->free(page);
   return r;
 }
 
-static int
-wizard_page
-  ( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp, const char *page )
-{
-  pthread_mutex_lock(&global_lock);
-  free(config.wizard);
-  config.wizard = strdup(page);
-  config_save();
-  pthread_mutex_unlock(&global_lock);
-  return 0;
-}
-
 static int
 wizard_cancel
   ( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
 {
-  return wizard_page(perm, opaque, op, args, resp, "");
+  return wizard_page("");
 }
 
 static int
 wizard_start
   ( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
 {
-  return wizard_page(perm, opaque, op, args, resp, "hello");
+  return wizard_page("hello");
 }
 
 void
index 257cbfb16ecc907fdce63fafcc2f4ef29cf7f8a7..14a69f3ea08f59bc8bd8950e942ec8b852fbbd86 100644 (file)
@@ -935,7 +935,9 @@ htsmsg_copy_i(htsmsg_t *src, htsmsg_t *dst)
 htsmsg_t *
 htsmsg_copy(htsmsg_t *src)
 {
-  htsmsg_t *dst = src->hm_islist ? htsmsg_create_list() : htsmsg_create_map();
+  htsmsg_t *dst;
+  if (src == NULL) return NULL;
+  dst = src->hm_islist ? htsmsg_create_list() : htsmsg_create_map();
   htsmsg_copy_i(src, dst);
   return dst;
 }
index 960360a16d526e0c9650655e05e75e1fedabdd89..0decc89cbc3bf8ebf217379e7419a6afc94bca58 100644 (file)
@@ -22,6 +22,8 @@
 #include "idnode.h"
 #include "queue.h"
 
+struct htsmsg;
+
 /*
  * Type-defs
  */
@@ -87,6 +89,8 @@ struct tvh_input {
 
   void (*ti_get_streams) (tvh_input_t *, tvh_input_stream_list_t*);
   void (*ti_clear_stats) (tvh_input_t *);
+  struct htsmsg *(*ti_wizard_get) (tvh_input_t *, const char *);
+  void (*ti_wizard_set)  (tvh_input_t *, struct htsmsg *);
 };
 
 /*
index e8e425e19ba0057a81d8dcb631fd09f6fa812078..fbe1668e0a50a4c1ed12bc08a906aa7271a72869 100644 (file)
@@ -302,6 +302,8 @@ struct mpegts_network
    */
   char                    *mn_network_name;
   char                    *mn_provider_network_name;
+  int                      mn_wizard;
+  uint8_t                  mn_wizard_free;
 
   /*
    * Inputs
@@ -826,6 +828,7 @@ void mpegts_network_delete ( mpegts_network_t *mn, int delconf );
 int mpegts_network_set_nid          ( mpegts_network_t *mn, uint16_t nid );
 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 );
 
 mpegts_mux_t *mpegts_mux_create0
   ( mpegts_mux_t *mm, const idclass_t *class, const char *uuid,
index 91ff8edbce156bbb5b2fdfe3a4617741c3a0abe6..35b8475b96ed1635f8d0e256d692cdaedcc70d10 100644 (file)
@@ -251,6 +251,13 @@ const idclass_t mpegts_network_class =
       .opts     = PO_RDONLY | PO_NOSAVE,
       .get      = mpegts_network_class_get_scanq_length,
     },
+    {
+       .type     = PT_BOOL,
+       .id       = "wizard",
+       .name     = N_("Wizard"),
+       .off      = offsetof(mpegts_network_t, mn_wizard),
+       .opts     = PO_NOUI
+    },
     {}
   }
 };
@@ -449,6 +456,19 @@ mpegts_network_scan ( mpegts_network_t *mn )
     mpegts_mux_scan_state_set(mm, MM_SCAN_STATE_PEND);
 }
 
+void
+mpegts_network_get_type_str( mpegts_network_t *mn, char *buf, size_t buflen )
+{
+  const char *s = "IPTV";
+#if ENABLE_MPEGTS_DVB
+  dvb_fe_type_t ftype;
+  ftype = dvb_fe_type_by_network_class(mn->mn_id.in_class);
+  if (ftype != DVB_TYPE_NONE)
+    s = dvb_type2str(ftype);
+#endif
+  snprintf(buf, buflen, "%s", s);
+}
+
 /******************************************************************************
  * Network classes/creation
  *****************************************************************************/
index fa209f1dd32fddd505b1d7d9b9f3fade287dc99e..c1d1c6ab1b08cbec923dc2229edf8c4ca0257aee 100644 (file)
@@ -434,16 +434,7 @@ mpegts_service_setsourceinfo(service_t *t, source_info_t *si)
 
   if(m->mm_network->mn_network_name != NULL)
     si->si_network = strdup(m->mm_network->mn_network_name);
-#if ENABLE_MPEGTS_DVB
-  dvb_fe_type_t ftype;
-  ftype = dvb_fe_type_by_network_class(m->mm_network->mn_id.in_class);
-  if (ftype == DVB_TYPE_NONE)
-    strcpy(buf, "IPTV");
-  else
-    snprintf(buf, sizeof(buf), "%s", dvb_type2str(ftype));
-#else
-  strcpy(buf, "IPTV");
-#endif
+  mpegts_network_get_type_str(m->mm_network, buf, sizeof(buf));
   si->si_network_type = strdup(buf);
 
   m->mm_display_name(m, buf, sizeof(buf));
index 7b3d7e48782ced2b8a0963bab0f82afc950c9930..a725825d86c6268194b079aba25a27eb393fe878 100644 (file)
@@ -1752,8 +1752,69 @@ done:
  * Creation/Config
  * *************************************************************************/
 
+static int
+satip_frontend_default_positions ( satip_frontend_t *lfe )
+{
+  satip_device_t *sd = lfe->sf_device;
+
+  if (!strcmp(sd->sd_info.modelname, "IPLNB"))
+    return 1;
+  return sd->sd_info.srcs;
+}
+
+static htsmsg_t *
+satip_frontend_wizard_get( tvh_input_t *ti, const char *lang )
+{
+  satip_frontend_t *lfe = (satip_frontend_t*)ti;
+  htsmsg_t *m = htsmsg_create_map(), *l, *e;
+  satip_satconf_t *sfc;
+  const idclass_t *idc;
+  char ubuf[UUID_HEX_SIZE], buf[256];
+
+  sfc = TAILQ_FIRST(&lfe->sf_satconf);
+  if (sfc == NULL || (sfc && sfc->sfc_wizard)) {
+    lfe->mi_display_name((mpegts_input_t*)lfe, buf, sizeof(buf));
+    htsmsg_add_str(m, "input_name", buf);
+    idc = dvb_network_class_by_fe_type(lfe->sf_type);
+    if (idc) {
+      l = htsmsg_create_list();
+      e = htsmsg_create_map();
+      htsmsg_add_str(e, "key", idc->ic_class);
+      htsmsg_add_str(e, "val", idclass_get_caption(idc, lang));
+      htsmsg_add_msg(l, NULL, e);
+      htsmsg_add_msg(m, "mpegts_network_types", l);
+    }
+    if (sfc && sfc->sfc_wizard) {
+      lfe->mi_display_name((mpegts_input_t*)lfe, buf, sizeof(buf));
+      htsmsg_add_str(m, "input_name", buf);
+      htsmsg_add_str(m, "mpegts_network",
+                     idnode_uuid_as_str(sfc->sfc_networks->is_array[0], ubuf));
+    }
+  }
+  return m;
+}
+
+static void
+satip_frontend_wizard_set( tvh_input_t *ti, htsmsg_t *conf )
+{
+  satip_frontend_t *lfe = (satip_frontend_t*)ti;
+  const char *uuid = htsmsg_get_str(conf, "mpegts_network_type");
+  satip_satconf_t *sfc;
+
+  sfc = TAILQ_FIRST(&lfe->sf_satconf);
+  if (uuid && (sfc == NULL || sfc->sfc_wizard)) {
+    htsmsg_t *conf = htsmsg_create_map();
+    htsmsg_t *nlist = htsmsg_create_list();
+    htsmsg_add_str(nlist, NULL, uuid);
+    htsmsg_add_msg(conf, "networks", nlist);
+    htsmsg_add_bool(conf, "wizard", 1);
+    satip_satconf_create(lfe, conf, satip_frontend_default_positions(lfe));
+    htsmsg_destroy(conf);
+  }
+}
+
 static void
-satip_frontend_hacks( satip_frontend_t *lfe, int *def_positions )
+satip_frontend_hacks( satip_frontend_t *lfe )
 {
   satip_device_t *sd = lfe->sf_device;
 
@@ -1764,8 +1825,6 @@ satip_frontend_hacks( satip_frontend_t *lfe, int *def_positions )
       lfe->sf_play2 = 1;
     lfe->sf_tdelay = 250;
     lfe->sf_teardown_delay = 1;
-  } else if (!strcmp(sd->sd_info.modelname, "IPLNB")) {
-    *def_positions = 1;
   } else if (strstr(sd->sd_info.manufacturer, "AVM Berlin") &&
               strstr(sd->sd_info.modelname, "FRITZ!")) {
     lfe->sf_play2 = 1;
@@ -1781,7 +1840,7 @@ satip_frontend_create
   char id[16], lname[256], nname[60];
   satip_frontend_t *lfe;
   uint32_t master = 0;
-  int i, def_positions = sd->sd_info.srcs;
+  int i;
 
   /* Override type */
   snprintf(id, sizeof(id), "override #%d", num);
@@ -1838,7 +1897,7 @@ satip_frontend_create
   lfe->sf_master   = master;
   lfe->sf_type_override = override ? strdup(override) : NULL;
   lfe->sf_pass_weight = 1;
-  satip_frontend_hacks(lfe, &def_positions);
+  satip_frontend_hacks(lfe);
   TAILQ_INIT(&lfe->sf_satconf);
   pthread_mutex_init(&lfe->sf_dvr_lock, NULL);
   lfe = (satip_frontend_t*)mpegts_input_create0((mpegts_input_t*)lfe, idc, uuid, conf);
@@ -1865,6 +1924,8 @@ satip_frontend_create
   }
 
   /* Input callbacks */
+  lfe->ti_wizard_get     = satip_frontend_wizard_get;
+  lfe->ti_wizard_set     = satip_frontend_wizard_set;
   lfe->mi_is_enabled     = satip_frontend_is_enabled;
   lfe->mi_start_mux      = satip_frontend_start_mux;
   lfe->mi_stop_mux       = satip_frontend_stop_mux;
@@ -1879,7 +1940,7 @@ satip_frontend_create
 
   /* Create satconf */
   if (lfe->sf_type == DVB_TYPE_S && master == 0)
-    satip_satconf_create(lfe, conf, def_positions);
+    satip_satconf_create(lfe, conf, satip_frontend_default_positions(lfe));
 
   /* Slave networks update */
   if (master) {
index 21fd4a4404364877337284abaa9b649ae7a83d95..e0a349479c79db06d83500d2548f0db03a8815ee 100644 (file)
@@ -177,6 +177,7 @@ struct satip_satconf
   /*
    * Config
    */
+  int                        sfc_wizard;
   int                        sfc_enabled;
   int                        sfc_position;
   int                        sfc_priority;
index 35254c09ec2b9b52fabe6f6935cd995747683358..e60f7e102631f2a7b85e0ce6bf231e185ed64420 100644 (file)
@@ -183,6 +183,13 @@ const idclass_t satip_satconf_class =
   .ic_get_title  = satip_satconf_class_get_title,
   .ic_save       = satip_satconf_class_save,
   .ic_properties = (const property_t[]) {
+    {
+      .type     = PT_BOOL,
+      .id       = "wizard",
+      .name     = N_("Wizard"),
+      .off      = offsetof(satip_satconf_t, sfc_wizard),
+      .opts     = PO_NOUI,
+    },
     {
       .type     = PT_BOOL,
       .id       = "enabled",
index 6bc9af8e81efcae427e7b9e26236ae91ff819c83..1551ea3eff114ef1a6dc18560e71a3102c63e7eb 100644 (file)
  * Extra LIST-ops
  */
 
+#define LIST_LAST(headname, head, field) ({ \
+        headname *r; \
+        for (r = LIST_FIRST(head); \
+             LIST_NEXT(r, field); \
+             r = LIST_NEXT(r, field)); \
+        r; \
+})
+
+#define LIST_PREV(elm, headname, head, field) ({ \
+        headname *r; \
+        for (r = LIST_FIRST(head); \
+             r && LIST_NEXT(r, field) != (elm); \
+             r = LIST_NEXT(r, field)); \
+        r; \
+})
+
 #define LIST_ENTRY_INIT(elm, field) \
         (elm)->field.le_next = NULL, (elm)->field.le_prev = NULL
 
index f49a6aded6d47e6cc48f059edffcc0ed4e0f5c2a..1dce07402fe9a5f5ca08d2671703d08326bab2bd 100644 (file)
@@ -87,10 +87,12 @@ static void page_free(wizard_page_t *page)
   free(page);
 }
 
-static wizard_page_t *page_init(const char *class_name, const char *caption)
+static wizard_page_t *page_init
+  (const char *name, const char *class_name, const char *caption)
 {
   wizard_page_t *page = calloc(1, sizeof(*page));
   idclass_t *ic = calloc(1, sizeof(*ic));
+  page->name = name;
   page->idnode.in_class = ic;
   ic->ic_caption = caption;
   ic->ic_class = ic->ic_event = class_name;
@@ -165,7 +167,7 @@ Enter the languages for the web user interface and \
 for EPG texts.\
 "))
 
-wizard_page_t *wizard_hello(void)
+wizard_page_t *wizard_hello(const char *lang)
 {
   static const property_group_t groups[] = {
     {
@@ -221,7 +223,7 @@ wizard_page_t *wizard_hello(void)
     {}
   };
   wizard_page_t *page =
-    page_init("wizard_hello",
+    page_init("hello", "wizard_hello",
     N_("Welcome - Tvheadend - your TV streaming server and video recorder"));
   idclass_t *ic = (idclass_t *)page->idnode.in_class;
   wizard_hello_t *w;
@@ -369,7 +371,7 @@ This wizard should be run only on the initial setup. Please, cancel \
 it, if you are not willing to touch the current configuration.\
 "))
 
-wizard_page_t *wizard_login(void)
+wizard_page_t *wizard_login(const char *lang)
 {
   static const property_group_t groups[] = {
     {
@@ -434,7 +436,7 @@ wizard_page_t *wizard_login(void)
     {}
   };
   wizard_page_t *page =
-    page_init("wizard_login",
+    page_init("login", "wizard_login",
     N_("Welcome - Tvheadend - your TV streaming server and video recorder"));
   idclass_t *ic = (idclass_t *)page->idnode.in_class;
   wizard_login_t *w;
@@ -477,78 +479,206 @@ wizard_page_t *wizard_login(void)
 /*
  * Network settings
  */
+#define WIZARD_NETWORKS 6
 
 typedef struct wizard_network {
-  char network_type1[32];
-  char network_type2[32];
-  char network_type3[32];
-  char network_type4[32];
+  property_t props [WIZARD_NETWORKS * 3 + 10];
+  char tuner       [WIZARD_NETWORKS][64];
+  char tunerid     [WIZARD_NETWORKS][UUID_HEX_SIZE];
+  char network_type[WIZARD_NETWORKS][64];
+  htsmsg_t *network_types[WIZARD_NETWORKS];
 } wizard_network_t;
 
-#define NETWORK(num, nameval) { \
+static void network_free(wizard_page_t *page)
+{
+  wizard_network_t *w = page->aux;
+  int idx;
+
+  for (idx = 0; idx < WIZARD_NETWORKS; idx++)
+    htsmsg_destroy(w->network_types[idx]);
+  page_free(page);
+}
+
+static void network_save(idnode_t *in)
+{
+  wizard_page_t *p = (wizard_page_t *)in;
+  wizard_network_t *w = p->aux;
+  mpegts_network_t *mn, *mn_next;
+  tvh_input_t *ti;
+  htsmsg_t *m;
+  int idx;
+
+  LIST_FOREACH(mn, &mpegts_network_all, mn_global_link)
+    if (mn->mn_wizard)
+      mn->mn_wizard_free = 1;
+  for (idx = 0; idx < WIZARD_NETWORKS; idx++) {
+    if (w->network_type[idx][0] == '\0')
+      continue;
+    ti = tvh_input_find_by_uuid(w->tunerid[idx]);
+    if (ti == NULL || ti->ti_wizard_set == NULL)
+      continue;
+    m = htsmsg_create_map();
+    htsmsg_add_str(m, "mpegts_network_type", w->network_type[idx]);
+    ti->ti_wizard_set(ti, m);
+    htsmsg_destroy(m);
+  }
+  for (mn = LIST_FIRST(&mpegts_network_all); mn != NULL; mn = mn_next) {
+    mn_next = LIST_NEXT(mn, mn_global_link);
+    if (mn->mn_wizard_free)
+      mn->mn_delete(mn, 1);
+  }
+}
+
+#define NETWORK_GROUP(num) { \
+  .name     = N_("Network " STRINGIFY(num)), \
+  .number   = num, \
+}
+
+#define NETWORK(num) { \
+  .type = PT_STR, \
+  .id   = "tuner" STRINGIFY(num), \
+  .name = N_("Tuner"), \
+  .get  = network_get_tvalue##num, \
+  .opts = PO_RDONLY, \
+  .group = num, \
+}, { \
+  .type = PT_STR, \
+  .id   = "hidden_tunerid" STRINGIFY(num), \
+  .name = "Tuner", \
+  .get  = network_get_tidvalue##num, \
+  .opts = PO_RDONLY | PO_NOUI, \
+}, { \
   .type = PT_STR, \
   .id   = "network" STRINGIFY(num), \
-  .name = nameval, \
+  .name = N_("Network type"), \
   .get  = network_get_value##num, \
   .set  = network_set_value##num, \
-  .list = network_get_list, \
+  .list = network_get_list##num, \
+  .group = num, \
 }
 
 #define NETWORK_FCN(num) \
+static const void *network_get_tvalue##num(void *o) \
+{ \
+  wizard_page_t *p = o; \
+  wizard_network_t *w = p->aux; \
+  snprintf(prop_sbuf, PROP_SBUF_LEN, "%s", w->tuner[num-1]); \
+  return &prop_sbuf_ptr; \
+} \
+static const void *network_get_tidvalue##num(void *o) \
+{ \
+  wizard_page_t *p = o; \
+  wizard_network_t *w = p->aux; \
+  snprintf(prop_sbuf, PROP_SBUF_LEN, "%s", w->tunerid[num-1]); \
+  return &prop_sbuf_ptr; \
+} \
 static const void *network_get_value##num(void *o) \
 { \
   wizard_page_t *p = o; \
   wizard_network_t *w = p->aux; \
-  snprintf(prop_sbuf, PROP_SBUF_LEN, "%s", w->network_type##num); \
+  snprintf(prop_sbuf, PROP_SBUF_LEN, "%s", w->network_type[num-1]); \
   return &prop_sbuf_ptr; \
 } \
 static int network_set_value##num(void *o, const void *v) \
 { \
   wizard_page_t *p = o; \
   wizard_network_t *w = p->aux; \
-  snprintf(w->network_type##num, sizeof(w->network_type##num), "%s", (const char *)v); \
+  snprintf(w->network_type[num-1], sizeof(w->network_type[num-1]), "%s", (const char *)v); \
   return 1; \
+} \
+static htsmsg_t *network_get_list##num(void *o, const char *lang) \
+{ \
+  if (o == NULL) return NULL; \
+  wizard_page_t *p = o; \
+  wizard_network_t *w = p->aux; \
+  return htsmsg_copy(w->network_types[num-1]); \
 }
 
 NETWORK_FCN(1)
 NETWORK_FCN(2)
 NETWORK_FCN(3)
 NETWORK_FCN(4)
+NETWORK_FCN(5)
+NETWORK_FCN(6)
 
 DESCRIPTION_FCN(network, N_("\
-Create networks. The T means terresterial, C is cable and S is satellite.\
+Select network type for detected tuners.\n\
+The T means terresterial, C is cable and S is satellite.\
 "))
 
-static htsmsg_t *network_get_list(void *o, const char *lang)
-{
-  mpegts_network_builder_t *mnb;
-  htsmsg_t *e, *l = htsmsg_create_list();
-  LIST_FOREACH(mnb, &mpegts_network_builders, link) {
-    e = htsmsg_create_map();
-    htsmsg_add_str(e, "key", mnb->idc->ic_class);
-    htsmsg_add_str(e, "val", idclass_get_caption(mnb->idc, lang));
-    htsmsg_add_msg(l, NULL, e);
-  }
-  return l;
-}
 
-wizard_page_t *wizard_network(void)
+wizard_page_t *wizard_network(const char *lang)
 {
+  static const property_group_t groups[] = {
+    NETWORK_GROUP(1),
+    NETWORK_GROUP(2),
+    NETWORK_GROUP(3),
+    NETWORK_GROUP(4),
+    NETWORK_GROUP(5),
+    NETWORK_GROUP(6),
+    {}
+  };
+  static const property_t nprops[] = {
+    NETWORK(1),
+    NETWORK(2),
+    NETWORK(3),
+    NETWORK(4),
+    NETWORK(5),
+    NETWORK(6),
+  };
   static const property_t props[] = {
-    NETWORK(1, N_("Network 1")),
-    NETWORK(2, N_("Network 2")),
-    NETWORK(3, N_("Network 3")),
-    NETWORK(4, N_("Network 4")),
     ICON(),
     DESCRIPTION(network),
     PREV_BUTTON(login),
     NEXT_BUTTON(input),
-    {}
   };
-  wizard_page_t *page = page_init("wizard_network", N_("Network settings"));
+  wizard_page_t *page = page_init("network", "wizard_network", N_("Network settings"));
   idclass_t *ic = (idclass_t *)page->idnode.in_class;
-  ic->ic_properties = props;
-  page->aux = calloc(1, sizeof(wizard_network_t));
+  wizard_network_t *w;
+  mpegts_network_t *mn;
+  tvh_input_t *ti;
+  const char *name;
+  htsmsg_t *m;
+  int idx, nidx = 0;
+
+  page->aux = w = calloc(1, sizeof(wizard_network_t));
+  ic->ic_groups = groups;
+  ic->ic_properties = w->props;
+  ic->ic_save = network_save;
+  page->free = network_free;
+
+  for (idx = 0; idx < ARRAY_SIZE(props); idx++)
+    w->props[idx] = props[idx];
+
+  for (ti = LIST_LAST(tvh_input_t, &tvh_inputs, ti_link); ti;
+       ti = LIST_PREV(ti, tvh_input_t, &tvh_inputs, ti_link)) {
+    if (ti->ti_wizard_get == NULL)
+      continue;
+    m = ti->ti_wizard_get(ti, lang);
+    if (m == NULL)
+      continue;
+    name = htsmsg_get_str(m, "input_name");
+    if (name) {
+      snprintf(w->tuner[nidx], sizeof(w->tuner[nidx]), "%s", name);
+      idnode_uuid_as_str(&ti->ti_id, w->tunerid[nidx]);
+      mn = mpegts_network_find(htsmsg_get_str(m, "mpegts_network"));
+      if (mn) {
+        snprintf(w->network_type[nidx], sizeof(w->network_type[nidx]), "%s",
+                 mn->mn_id.in_class->ic_class);
+      }
+      w->network_types[nidx] = htsmsg_copy(htsmsg_get_list(m, "mpegts_network_types"));
+      w->props[idx++] = nprops[nidx * 3 + 0];
+      w->props[idx++] = nprops[nidx * 3 + 1];
+      w->props[idx++] = nprops[nidx * 3 + 2];
+      nidx++;
+    }
+    htsmsg_destroy(m);
+    if (nidx >= WIZARD_NETWORKS)
+      break;
+  }
+
+  assert(idx < ARRAY_SIZE(w->props));
+
   return page;
 }
 
@@ -561,7 +691,7 @@ Assign inputs to networks.\
 "))
 
 
-wizard_page_t *wizard_input(void)
+wizard_page_t *wizard_input(const char *lang)
 {
   static const property_t props[] = {
     {
@@ -591,7 +721,7 @@ wizard_page_t *wizard_input(void)
     NEXT_BUTTON(status),
     {}
   };
-  wizard_page_t *page = page_init("wizard_input", N_("Input / tuner settings"));
+  wizard_page_t *page = page_init("input", "wizard_input", N_("Input / tuner settings"));
   idclass_t *ic = (idclass_t *)page->idnode.in_class;
   ic->ic_properties = props;
   return page;
@@ -606,7 +736,7 @@ Show the scan status.\
 "))
 
 
-wizard_page_t *wizard_status(void)
+wizard_page_t *wizard_status(const char *lang)
 {
   static const property_t props[] = {
     {
@@ -631,7 +761,7 @@ wizard_page_t *wizard_status(void)
     NEXT_BUTTON(mapping),
     {}
   };
-  wizard_page_t *page = page_init("wizard_status", N_("Scan status"));
+  wizard_page_t *page = page_init("status", "wizard_status", N_("Scan status"));
   idclass_t *ic = (idclass_t *)page->idnode.in_class;
   ic->ic_properties = props;
   return page;
@@ -646,7 +776,7 @@ Do the service mapping to channels.\
 "))
 
 
-wizard_page_t *wizard_mapping(void)
+wizard_page_t *wizard_mapping(const char *lang)
 {
   static const property_t props[] = {
     {
@@ -663,7 +793,7 @@ wizard_page_t *wizard_mapping(void)
     LAST_BUTTON(),
     {}
   };
-  wizard_page_t *page = page_init("wizard_service_map", N_("Service mapping"));
+  wizard_page_t *page = page_init("mapping", "wizard_service_map", N_("Service mapping"));
   idclass_t *ic = (idclass_t *)page->idnode.in_class;
   ic->ic_properties = props;
   return page;
index b0bef71f047338a4031192687897aac5d61b0fe6..71768b9eb10c6f92f8e7185efdd27a1321c0d412 100644 (file)
 
 typedef struct wizard_page {
   idnode_t idnode;
+  const char *name;
   void (*free)(struct wizard_page *);
   void *aux;
 } wizard_page_t;
 
-typedef wizard_page_t *(*wizard_build_fcn_t)(void);
+typedef wizard_page_t *(*wizard_build_fcn_t)(const char *lang);
 
-wizard_page_t *wizard_hello(void);
-wizard_page_t *wizard_login(void);
-wizard_page_t *wizard_network(void);
-wizard_page_t *wizard_input(void);
-wizard_page_t *wizard_status(void);
-wizard_page_t *wizard_mapping(void);
+wizard_page_t *wizard_hello(const char *lang);
+wizard_page_t *wizard_login(const char *lang);
+wizard_page_t *wizard_network(const char *lang);
+wizard_page_t *wizard_input(const char *lang);
+wizard_page_t *wizard_status(const char *lang);
+wizard_page_t *wizard_mapping(const char *lang);
 
 #endif /* __TVH_WIZARD_H__ */