]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
use individual files for storing configuration. This is not so error prone.
authorAndreas Öman <andreas@lonelycoder.com>
Mon, 28 Jan 2008 20:40:35 +0000 (20:40 +0000)
committerAndreas Öman <andreas@lonelycoder.com>
Mon, 28 Jan 2008 20:40:35 +0000 (20:40 +0000)
Also, use a better naming scheme for DVB adapters (adapter vendor name + a sequence id)

channels.c
channels.h
dvb.c
dvb_muxconfig.c
htmlui.c
main.c
transports.c
transports.h
tvhead.h

index 1aae67600df2888056c9f0286a1721b6358a274c..68d0be8493245eed443a6839bff79e47eee85357 100644 (file)
@@ -27,6 +27,7 @@
 #include <unistd.h>
 #include <stdlib.h>
 #include <string.h>
+#include <dirent.h>
 
 #include <libhts/htscfg.h>
 
@@ -38,6 +39,9 @@
 #include "channels.h"
 #include "transports.h"
 
+static void channel_group_settings_write(void);
+static void channel_settings_write(th_channel_t *ch);
+
 struct th_channel_list channels;
 struct th_transport_list all_transports;
 int nchannels;
@@ -46,7 +50,6 @@ struct th_channel_group_queue all_channel_groups;
 
 th_channel_group_t *defgroup;
 
-static int dontwritesettings;
 
 void scanner_init(void);
 
@@ -112,8 +115,7 @@ channel_group_find(const char *name, int create)
 
   TAILQ_INSERT_TAIL(&all_channel_groups, tcg, tcg_global_link);
 
-  channel_settings_write();
-
+  channel_group_settings_write();
   return tcg;
 }
 
@@ -131,7 +133,18 @@ channel_set_group(th_channel_t *ch, th_channel_group_t *tcg)
 
   ch->ch_group = tcg;
   TAILQ_INSERT_SORTED(&tcg->tcg_channels, ch, ch_group_link, channelcmp);
-  channel_settings_write();
+
+  channel_settings_write(ch);
+}
+
+/**
+ *
+ */
+void
+channel_set_teletext_rundown(th_channel_t *ch, int v)
+{
+  ch->ch_teletext_rundown = v;
+  channel_settings_write(ch);
 }
 
 /**
@@ -152,6 +165,8 @@ channel_group_destroy(th_channel_group_t *tcg)
   TAILQ_REMOVE(&all_channel_groups, tcg, tcg_global_link);
   free((void *)tcg->tcg_name);
   free(tcg);
+
+  channel_group_settings_write();
 }
 
 /**
@@ -241,54 +256,80 @@ service_load(struct config_head *head)
 void
 channels_load(void)
 {
-  config_entry_t *ce, *ce1, *ce2;
-  const char *name;
-  th_channel_group_t *tcg;
+  struct config_head cl;
+  config_entry_t *ce;
+  char buf[400];
+  DIR *dir;
+  struct dirent *d;
+  const char *name, *grp;
   th_channel_t *ch;
-
-  dontwritesettings = 1;
+  th_channel_group_t *tcg;
 
   TAILQ_INIT(&all_channel_groups);
+  TAILQ_INIT(&cl);
 
-  TAILQ_FOREACH(ce1, &settings_list, ce_link) {
-    if(ce1->ce_type != CFG_SUB || strcasecmp("channel-group", ce1->ce_key))
+  snprintf(buf, sizeof(buf), "%s/channel-group-settings.cfg", settings_dir);
+  config_read_file0(buf, &cl);
+
+  TAILQ_FOREACH(ce, &cl, ce_link) {
+    if(ce->ce_type != CFG_SUB || strcasecmp("channel-group", ce->ce_key))
+      continue;
+     
+    if((name = config_get_str_sub(&ce->ce_sub, "name", NULL)) == NULL)
       continue;
-    
-    if((name = config_get_str_sub(&ce1->ce_sub, "name", NULL)) == NULL)
+
+    printf("Added channel group %s\n", name);
+    channel_group_find(name, 1);
+  }
+  config_free0(&cl);
+
+  snprintf(buf, sizeof(buf), "%s/channels", settings_dir);
+
+  if((dir = opendir(buf)) == NULL)
+    return;
+  
+  while((d = readdir(dir)) != NULL) {
+
+    if(d->d_name[0] == '.')
       continue;
 
-    tcg = channel_group_find(name, 1);
-    TAILQ_FOREACH(ce2, &ce1->ce_sub, ce_link) {
-      if(ce2->ce_type != CFG_SUB || strcasecmp("channel", ce2->ce_key))
-       continue;
+    snprintf(buf, sizeof(buf), "%s/channels/%s", settings_dir, d->d_name);
+    TAILQ_INIT(&cl);
+    config_read_file0(buf, &cl);
 
-      if((name = config_get_str_sub(&ce2->ce_sub, "name", NULL)) == NULL)
-       continue;
+    if((name = config_get_str_sub(&cl, "name", NULL)) == NULL)
+      continue;
 
-      ch = channel_find(name, 1, tcg);
+    if((grp = config_get_str_sub(&cl, "channel-group", NULL)) == NULL)
+      continue;
+
+    tcg = channel_group_find(grp, 1);
+    ch = channel_find(name, 1, tcg);
       
-      ch->ch_teletext_rundown = 
-       atoi(config_get_str_sub(&ce2->ce_sub, "teletext-rundown", "0"));
-    }
+    ch->ch_teletext_rundown = 
+      atoi(config_get_str_sub(&cl, "teletext-rundown", "0"));
+
+    config_free0(&cl);
   }
 
   tcg = channel_group_find("-disabled-", 1);
   tcg->tcg_cant_delete_me = 1;
   tcg->tcg_hidden = 1;
-
+  
   defgroup = channel_group_find("Uncategorized", 1);
   defgroup->tcg_cant_delete_me = 1;
+  
+  /* Static services */
 
   TAILQ_FOREACH(ce, &config_list, ce_link) {
     if(ce->ce_type == CFG_SUB && !strcasecmp("service", ce->ce_key)) {
       service_load(&ce->ce_sub);
     }
   }
-  dontwritesettings = 0;
-
 }
 
 
+
 /**
  * The index stuff should go away
  */
@@ -347,7 +388,8 @@ channel_group_move_next(th_channel_group_t *tcg)
 
   TAILQ_REMOVE(&all_channel_groups, tcg, tcg_global_link);
   TAILQ_INSERT_AFTER(&all_channel_groups, n, tcg, tcg_global_link);
-  channel_settings_write();
+
+  channel_group_settings_write();
 }
 
 void
@@ -360,57 +402,54 @@ channel_group_move_prev(th_channel_group_t *tcg)
 
   TAILQ_REMOVE(&all_channel_groups, tcg, tcg_global_link);
   TAILQ_INSERT_BEFORE(p, tcg, tcg_global_link);
-  channel_settings_write();
+  channel_group_settings_write();
 }
 
 
-
 /**
+ * Write out a config file with all channel groups
  *
+ * We do this to maintain order of groups
  */
-void
-channel_settings_write(void)
+static void
+channel_group_settings_write(void)
 {
   FILE *fp;
   th_channel_group_t *tcg;
-  th_channel_t *ch;
-  th_transport_t *t;
 
-  if(dontwritesettings || startupcounter > 0 || settingsfile == NULL)
-    return;
+  char buf[400];
+  snprintf(buf, sizeof(buf), "%s/channel-group-settings.cfg", settings_dir);
 
-  fp = fopen(settingsfile, "w+");
-  if(fp == NULL)
+  if((fp = settings_open_for_write(buf)) == NULL)
     return;
 
   TAILQ_FOREACH(tcg, &all_channel_groups, tcg_global_link) {
     fprintf(fp, "channel-group {\n"
            "\tname = %s\n", tcg->tcg_name);
-    TAILQ_FOREACH(ch, &tcg->tcg_channels, ch_group_link) {
-      if(LIST_FIRST(&ch->ch_transports) == NULL)
-       continue;
-
-      fprintf(fp, "\tchannel {\n"
-             "\t\tname = %s\n", ch->ch_name);
-      if(ch->ch_teletext_rundown)
-       fprintf(fp, "\t\tteletext-rundown = %d\n", ch->ch_teletext_rundown);
-      fprintf(fp, "\t}\n");
-    }
     fprintf(fp, "}\n");
   }
+  fclose(fp);
+}
 
-  LIST_FOREACH(t, &all_transports, tht_global_link) {
-    if(t->tht_channel == NULL)
-      continue;
 
-    fprintf(fp, "transport {\n"
-           "\tuniquename = %s\n"
-           "\tchannel = %s\n"
-           "\tprio = %d\n"
-           "}\n",
-           t->tht_uniquename,
-           t->tht_channel->ch_name,
-           t->tht_prio);
-  }
+
+/**
+ * Write out a config file for a channel
+ */
+static void
+channel_settings_write(th_channel_t *ch)
+{
+  FILE *fp;
+  char buf[400];
+
+  snprintf(buf, sizeof(buf), "%s/channels/%s", settings_dir, ch->ch_sname);
+  if((fp = settings_open_for_write(buf)) == NULL)
+    return;
+
+  fprintf(fp, "name = %s\n", ch->ch_name);
+  fprintf(fp, "channel-group = %s\n", ch->ch_group->tcg_name);
+  if(ch->ch_teletext_rundown)
+    fprintf(fp, "teletext-rundown = %d\n", ch->ch_teletext_rundown);
   fclose(fp);
 }
+
index fbb1b77d83eabe1e55793a22f46715f2a5304597..d4414c4d019129f06fec3cf2901a5c088ac7efc9 100644 (file)
@@ -44,8 +44,8 @@ void channel_group_move_prev(th_channel_group_t *tcg);
 
 void channel_group_move_next(th_channel_group_t *tcg);
 
-void channel_settings_write(void);
-
 void channel_set_group(th_channel_t *ch, th_channel_group_t *tcg);
 
+void channel_set_teletext_rundown(th_channel_t *ch, int v);
+
 #endif /* CHANNELS_H */
diff --git a/dvb.c b/dvb.c
index 19f0bfa9a600e9b239a15b86ba48e26b3c99ff10..9139bed2a1d14ac1cd814ef133c46ec5e34c0dd9 100644 (file)
--- a/dvb.c
+++ b/dvb.c
@@ -23,7 +23,7 @@
 #include <sys/ioctl.h>
 #include <fcntl.h>
 #include <errno.h>
-
+#include <ctype.h>
 #include <stdio.h>
 #include <unistd.h>
 #include <stdlib.h>
@@ -63,8 +63,10 @@ static void
 dvb_add_adapter(const char *path)
 {
   char fname[256];
-  int fe;
-  th_dvb_adapter_t *tda;
+  int fe, i, r;
+  th_dvb_adapter_t *tda, *x;
+  char c;
+  char buf[400], *cp;
 
   snprintf(fname, sizeof(fname), "%s/frontend0", path);
   
@@ -103,11 +105,44 @@ dvb_add_adapter(const char *path)
   pthread_cond_init(&tda->tda_cond, NULL);
   TAILQ_INIT(&tda->tda_fe_cmd_queue);
 
-  LIST_INSERT_HEAD(&dvb_adapters_probing, tda, tda_link);
   startupcounter++;
 
   tda->tda_info = strdup(tda->tda_fe_info->name);
 
+  /*
+   * Generate a decent unique name for the adapter.
+   * If multiple adapters with the same name is found, we add
+   * a sequence number at the end
+   */
+
+  for(i = 0; i < strlen(tda->tda_info); i++) {
+    c = tolower(tda->tda_info[i]);
+    if(isalnum(c))
+      buf[i] = c;
+    else
+      buf[i] = '_';
+  }
+  cp = &buf[i];
+
+  r = 0;
+
+ again:
+  if(r)
+    sprintf(cp, "-%d", r);
+  else
+    *cp = 0;
+  
+  LIST_FOREACH(x, &dvb_adapters_probing, tda_link) {
+    if(!strcmp(buf, x->tda_sname)) {
+      r++;
+      goto again;
+    }
+  }
+
+  tda->tda_sname = strdup(buf);
+
+  LIST_INSERT_HEAD(&dvb_adapters_probing, tda, tda_link);
+
   syslog(LOG_INFO, "Adding adapter %s (%s)", path, tda->tda_fe_info->name);
   dtimer_arm(&tda->tda_fec_monitor_timer, dvb_fec_monitor, tda, 1);
 
@@ -184,10 +219,13 @@ dvb_find_transport(th_dvb_mux_instance_t *tdmi, uint16_t tid,
   t->tht_dvb_mux_instance = tdmi;
 
   snprintf(tmp, sizeof(tmp), "%s/%04x", tdmi->tdmi_uniquename, sid);
-
   free((void *)t->tht_uniquename);
   t->tht_uniquename = strdup(tmp);
+
+  snprintf(tmp, sizeof(tmp), "%s/%04x", tdmi->tdmi_shortname, sid);
+  free((void *)t->tht_name);
   t->tht_name = strdup(tmp);
+
   LIST_INSERT_HEAD(&all_transports, t, tht_global_link);
 
   dvb_table_add_transport(tdmi, t, pmt_pid);
index 5193e7733dd4c4d2b87487670ac59ed258368887..cc940fdbfa1f1e816681be5431e61989c069995e 100644 (file)
@@ -81,7 +81,7 @@ dvb_add_mux(struct dvb_frontend_parameters *fe_param, fe_type_t type)
     /* Generate names */
     
     snprintf(buf, sizeof(buf), "%s/%s/%.1fMHz",
-            tda->tda_rootpath, typetxt,
+            tda->tda_sname, typetxt,
             (float)fe_param->frequency / 1000000.0f);
     tdmi->tdmi_uniquename = strdup(buf);
 
index 203f43a2ae8107434c1c79a6a54a2d8c537feb3a..2a1c3a500f1ae20dc81ce0194ae9904f2d27a8c0 100644 (file)
--- a/htmlui.c
+++ b/htmlui.c
@@ -1510,7 +1510,7 @@ page_editchannel(http_connection_t *hc, const char *remain, void *opaque)
                t->tht_scrambled ? "Yes" : "No",
                t->tht_provider,
                t->tht_network,
-               t->tht_uniquename);
+               t->tht_name);
 
   }
 
@@ -1562,7 +1562,7 @@ page_updatechannel(http_connection_t *hc, const char *remain, void *opaque)
   }
 
   if((s = http_arg_get(&hc->hc_url_args, "ttrp")) != NULL)
-    ch->ch_teletext_rundown = atoi(s);
+    channel_set_teletext_rundown(ch, atoi(s));
 
   if((grp = http_arg_get(&hc->hc_url_args, "grp")) != NULL) {
     tcg = channel_group_find(grp, 1);
diff --git a/main.c b/main.c
index 5ad59f041526f60938dba78e0b000f51d0d2492a..303bd03a08c7eaf19fcde70b14126b2e134b6da2 100644 (file)
--- a/main.c
+++ b/main.c
@@ -61,6 +61,7 @@ int running;
 int xmltvreload;
 int startupcounter;
 const char *tvheadend_streaming_host;
+const char *settings_dir;
 
 static pthread_mutex_t tag_mutex = PTHREAD_MUTEX_INITIALIZER;
 static uint32_t tag_tally;
@@ -114,6 +115,7 @@ main(int argc, char **argv)
   int logfacility = LOG_DAEMON;
   int disable_dvb = 0;
   int p;
+  char buf[400];
 
   signal(SIGPIPE, handle_sigpipe);
 
@@ -168,7 +170,18 @@ main(int argc, char **argv)
 
   openlog("tvheadend", LOG_PID, logfacility);
   
-  syslog(LOG_NOTICE, "Started HTS TV Headend");
+  settings_dir = config_get_str("settings-dir", "/tmp/tvheadend");
+  mkdir(settings_dir, 0777);
+
+  snprintf(buf, sizeof(buf), "%s/channels", settings_dir);
+  mkdir(buf, 0777);
+
+  snprintf(buf, sizeof(buf), "%s/transports", settings_dir);
+  mkdir(buf, 0777);
+
+
+  syslog(LOG_NOTICE, "Started HTS TV Headend, settings located in \"%s\"",
+        settings_dir);
 
   dispatch_init();
 
@@ -206,15 +219,14 @@ main(int argc, char **argv)
   while(running) {
 
     if(startupcounter == 0) {
-      channel_settings_write();
-
-      startupcounter = -1;
       syslog(LOG_NOTICE, 
             "Initial input setup completed, starting output modules");
 
       fprintf(stderr,
              "Initial input setup completed, starting output modules\n");
 
+      startupcounter = -1;
+
       pvr_init();
       output_multicast_setup();
       client_start();
@@ -343,3 +355,17 @@ htstvstreamtype2txt(tv_streamtype_t s)
   default:               return "<unknown>";
   }
 }
+
+
+FILE *
+settings_open_for_write(const char *name)
+{
+  FILE *fp;
+
+  fp = fopen(name, "w+");
+  if(fp == NULL)
+    syslog(LOG_ALERT, "Unable to open settings file \"%s\" -- %s",
+          name, strerror(errno));
+  return fp;
+}
+
index 7058f1edfcb2a2eda31ee0103544f1d4b1e20a3e..d26075e2ec7a6ee3b62aa8bc33b077b429602891 100644 (file)
@@ -25,7 +25,7 @@
 #include <sys/ioctl.h>
 #include <fcntl.h>
 #include <errno.h>
-
+#include <ctype.h>
 #include <stdio.h>
 #include <unistd.h>
 #include <stdlib.h>
@@ -57,6 +57,7 @@
 
 static dtimer_t transport_monitor_timer;
 
+static const char *transport_settings_path(th_transport_t *t);
 
 
 void
@@ -400,27 +401,22 @@ transport_set_channel(th_transport_t *t, th_channel_t *ch)
   th_stream_t *st;
   char *chname;
   const char *n;
-  config_entry_t *ce;
   char pid[30];
   char lang[30];
+  struct config_head cl;
 
   assert(t->tht_uniquename != NULL);
 
-  TAILQ_FOREACH(ce, &settings_list, ce_link) {
-    if(ce->ce_type != CFG_SUB || strcasecmp("transport", ce->ce_key))
-      continue;
+  n = transport_settings_path(t);
+  TAILQ_INIT(&cl);
+  config_read_file0(n, &cl);
 
-    n = config_get_str_sub(&ce->ce_sub, "uniquename", NULL);
-    if(n != NULL && !strcmp(n, t->tht_uniquename))
-      break;
-  }
+  t->tht_prio = atoi(config_get_str_sub(&cl, "prio", "0"));
+  n = config_get_str_sub(&cl, "channel", NULL);
+  if(n != NULL)
+    ch = channel_find(n, 1, NULL); 
 
-  if(ce != NULL) {
-    t->tht_prio = atoi(config_get_str_sub(&ce->ce_sub, "prio", "0"));
-    n = config_get_str_sub(&ce->ce_sub, "channel", NULL);
-    if(n != NULL)
-      ch = channel_find(n, 1, NULL); 
-  }
+  config_free0(&cl);
 
   t->tht_channel = ch;
   LIST_INSERT_SORTED(&ch->ch_transports, t, tht_channel_link, transportcmp);
@@ -464,10 +460,13 @@ transport_set_priority(th_transport_t *t, int prio)
 {
   th_channel_t *ch = t->tht_channel;
 
+  if(t->tht_prio == prio)
+    return;
+
   LIST_REMOVE(t, tht_channel_link);
   t->tht_prio = prio;
   LIST_INSERT_SORTED(&ch->ch_transports, t, tht_channel_link, transportcmp);
-  channel_settings_write();
+  transport_settings_write(t);
 }
 
 
@@ -480,5 +479,63 @@ transport_move(th_transport_t *t, th_channel_t *ch)
   LIST_REMOVE(t, tht_channel_link);
   t->tht_channel = ch;
   LIST_INSERT_SORTED(&ch->ch_transports, t, tht_channel_link, transportcmp);
-  channel_settings_write();
+  transport_settings_write(t);
 }
+
+
+/**
+ * Generate a settings-dir relative path to transport config
+ *
+ * Must be free'd by caller
+ */
+static const char *
+transport_settings_path(th_transport_t *t)
+{
+  char buf[400];
+  char buf2[400];
+
+  int l, i;
+  char c;
+
+  l = strlen(t->tht_uniquename);
+  if(l >= sizeof(buf2))
+      l = sizeof(buf2) - 1;
+
+  for(i = 0; i < l; i++) {
+    c = tolower(t->tht_uniquename[i]);
+    if(isalnum(c))
+      buf2[i] = c;
+    else
+      buf2[i] = '_';
+  }
+
+  buf2[i] = 0;
+  snprintf(buf, sizeof(buf), "%s/transports/%s", settings_dir, buf2);
+  return strdup(buf);
+}
+
+
+/**
+ * Write out a config file for a channel
+ */
+void
+transport_settings_write(th_transport_t *t)
+{
+  FILE *fp;
+  const char *n;
+
+  n = transport_settings_path(t);
+    
+  if((fp = settings_open_for_write(n)) != NULL) {
+    fprintf(fp, 
+           "uniquename = %s\n"
+           "channel = %s\n"
+           "prio = %d\n",
+           t->tht_uniquename,
+           t->tht_channel->ch_name,
+           t->tht_prio);
+    fclose(fp);
+  }
+  free((void *)n);
+}
+
index ae5c5ecd7a0730393ffb002118f42dd744372edf..095a03906cec6f30cb43e7b0e991291a44c06f68 100644 (file)
@@ -40,4 +40,6 @@ void transport_set_priority(th_transport_t *t, int prio);
 
 void transport_move(th_transport_t *t, th_channel_t *ch);
 
+void transport_settings_write(th_transport_t *t);
+
 #endif /* TRANSPORTS_H */
index b0de4bbff1e36ed2ca618d2d0cc617e1f882de97..ef9c3eff818c21d1afa8c869dab0626681b90fc1 100644 (file)
--- a/tvhead.h
+++ b/tvhead.h
@@ -210,6 +210,7 @@ typedef struct th_dvb_adapter {
 
   const char *tda_rootpath;
   const char *tda_info;
+  const char *tda_sname;
 
   LIST_ENTRY(th_dvb_adapter) tda_link;
 
@@ -759,5 +760,8 @@ char *utf8tofilename(const char *in);
 const char *htstvstreamtype2txt(tv_streamtype_t s);
 uint32_t tag_get(void);
 extern const char *tvheadend_streaming_host;
+extern const char *settings_dir;
+FILE *settings_open_for_write(const char *name);
+FILE *settings_open_for_read(const char *name);
 
 #endif /* TV_HEAD_H */