utils/dvb: add support for read the new format
authorMauro Carvalho Chehab <mchehab@redhat.com>
Wed, 4 Jan 2012 11:37:38 +0000 (09:37 -0200)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Sat, 7 Jan 2012 13:12:15 +0000 (11:12 -0200)
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
utils/dvb/dvb-fe.h
utils/dvb/dvb-file.c
utils/dvb/dvb-file.h
utils/dvb/dvb-v5-std.h
utils/dvb/dvb-v5.h
utils/dvb/dvbv5-zap.c
utils/dvb/gen_dvb_structs.pl

index 2507081..a166008 100644 (file)
@@ -113,6 +113,6 @@ int dvb_fe_diseqc_reply(struct dvb_v5_fe_parms *parms, unsigned *len, char *buf,
 
 /* Arrays from dvb-v5.h */
 
-extern const unsigned fe_bandwidth_name[7];
-extern const char *dvb_v5_name[45];
+extern const unsigned fe_bandwidth_name[8];
+extern const char *dvb_v5_name[46];
 extern const void *dvbv5_attr_names[];
index 4d306f0..f906977 100644 (file)
@@ -205,6 +205,193 @@ static const char *pol_name[] = {
        [POLARIZATION_R] = "RIGHT",
 };
 
+#define CHANNEL "CHANNEL"
+
+static int fill_entry(struct dvb_entry *entry, int n_prop,
+                      char *key, char *value)
+{
+       int i, j, len;
+       int is_video = 0, is_audio = 0;
+       uint16_t *pid = NULL;
+       char *p;
+
+       for (i = 0; i < ARRAY_SIZE(dvb_v5_name); i++) {
+               if (!dvb_v5_name[i])
+                       continue;
+               if (!strcasecmp(key, dvb_v5_name[i]))
+                       break;
+       }
+
+       /* Handle the DVBv5 DTV_foo properties */
+       if (i < ARRAY_SIZE(dvb_v5_name)) {
+               const char * const *attr_name = dvbv5_attr_names[i];
+
+               entry->props[n_prop].cmd = i;
+               if (!attr_name || !*attr_name)
+                       entry->props[n_prop].u.data = atol(value);
+               else {
+                       for (j = 0; !attr_name[j]; j++)
+                               if (!strcasecmp(value, attr_name[j]))
+                                       break;
+                       if (!attr_name[j])
+                               return -2;
+                       entry->props[n_prop].u.data = j;
+               }
+               return 0;
+       }
+
+       /* Handle the other properties */
+
+       if (!strcasecmp(key, "SERVICE_ID")) {
+               entry->service_id = atol(value);
+               return 0;
+       }
+
+       if (!strcasecmp(key, "VIDEO_PID"))
+               is_video = 1;
+       else    if (!strcasecmp(key, "AUDIO_PID"))
+               is_audio = 1;
+       else if (!strcasecmp(key, "POLARIZATION")) {
+               entry->service_id = atol(value);
+               for (j = 0; ARRAY_SIZE(pol_name); j++)
+                       if (!strcasecmp(value, pol_name[j]))
+                               break;
+               if (j == ARRAY_SIZE(pol_name))
+                       return -2;
+               entry->pol = j;
+               return 0;
+       }
+
+       if (!is_video && !is_audio)
+               return -1;
+
+       /* Video and audio may have multiple values */
+
+       len = 0;
+
+       p = strtok(value," \t");
+       if (!p)
+               return -2;
+       while (p) {
+               pid = realloc(pid, (len + 1) * sizeof (*pid));
+               pid[len] = atol(p);
+               p = strtok(NULL, " \t\n");
+               len++;
+       }
+
+       if (is_video)
+               entry->video_pid = pid;
+       else
+               entry->audio_pid = pid;
+
+       return 0;
+}
+
+
+struct dvb_file *read_dvb_file(const char *fname)
+{
+       char *buf = NULL, *p, *key, *value;
+       size_t size = 0;
+       int len = 0;
+       int line = 0, n_prop = 0, rc;
+       struct dvb_file *dvb_file;
+       FILE *fd;
+       struct dvb_entry *entry = NULL;
+       char err_msg[80];
+
+       dvb_file = calloc(sizeof(*dvb_file), 1);
+       if (!dvb_file) {
+               perror("Allocating memory for dvb_file");
+               return NULL;
+       }
+
+       fd = fopen(fname, "r");
+       if (!fd) {
+               perror(fname);
+               return NULL;
+       }
+
+       do {
+               len = getline(&buf, &size, fd);
+               if (len <= 0)
+                       break;
+               line++;
+               p = buf;
+               while (*p == ' ' || *p == '\t')
+                       p++;
+               if (*p == '\n' || *p == '#' || *p == '\a' || *p == '\0')
+                       continue;
+
+               if (*p == '[') {
+                       /* NEW Entry */
+                       if (!entry) {
+                               dvb_file->first_entry = calloc(sizeof(*entry), 1);
+                               entry = dvb_file->first_entry;
+                       } else {
+                               entry->next = calloc(sizeof(*entry), 1);
+                               entry = entry->next;
+                       }
+                       n_prop = 0;
+                       p++;
+                       p = strtok(p, "]");
+                       if (!p) {
+                               sprintf(err_msg, "Missing channel group");
+                               goto error;
+                       }
+                       if (!strcasecmp(p, CHANNEL))
+                               p += strlen(CHANNEL);
+                       while (*p == ' ' || *p == '\t')
+                               p++;
+                       if (*p) {
+                               entry->channel = calloc(strlen(p) + 1, 1);
+                               strcpy(entry->channel, p);
+printf("channel %s", entry->channel);
+                       }
+               } else {
+                       if (!entry) {
+                               sprintf(err_msg, "key/value without a channel group");
+                               goto error;
+                       }
+                       key = strtok(p, "=");
+                       if (!key) {
+                               sprintf(err_msg, "missing key");
+                               goto error;
+                       }
+                       p = &key[strlen(key) - 1];
+                       while (*p == ' ' || *p == '\t')
+                               p--;
+                       *p = 0;
+                       value = strtok(NULL, "\n");
+                       if (!value) {
+                               sprintf(err_msg, "missing value");
+                               goto error;
+                       }
+                       while (*value == ' ' || *value == '\t')
+                               value++;
+
+                       rc = fill_entry(entry, n_prop, key, value);
+                       if (rc == -2) {
+                               sprintf(err_msg, "value %s is invalid for %s",
+                                       value, key);
+                               goto error;
+                       } else if (rc == -2) {
+                               sprintf(err_msg, "key %s is unknown", key);
+                               goto error;
+                       }
+                       n_prop++;
+               }
+       } while (1);
+       fclose(fd);
+       return dvb_file;
+
+error:
+       fprintf (stderr, "ERROR %s while parsing line %d of %s\n",
+                err_msg, line, fname);
+       dvb_file_free(dvb_file);
+       fclose(fd);
+       return NULL;
+};
+
 int write_dvb_file(const char *fname, struct dvb_file *dvb_file)
 {
        FILE *fp;
index c8df794..1d506d1 100644 (file)
@@ -96,10 +96,12 @@ struct dvb_file *parse_format_oneline(const char *fname, const char *delimiter,
                                      uint32_t delsys,
                                      const struct parse_struct *formats);
 
+
+struct dvb_file *read_dvb_file(const char *fname);
+
 int write_dvb_file(const char *fname, struct dvb_file *dvb_file);
 
 int store_dvb_channel(struct dvb_file **dvb_file,
                      struct dvb_v5_fe_parms *parms,
                      struct dvb_descriptors *dvb_desc,
                      int get_detected);
-
index b9d9a3e..81f5ad4 100644 (file)
@@ -153,7 +153,7 @@ const unsigned int *dvb_v5_delivery_system[] = {
 const void *dvbv5_attr_names[] = {
        [0 ...DTV_MAX_COMMAND ] = NULL,
        [DTV_CODE_RATE_HP]              = fe_code_rate_name,
-       [DTV_CODE_RATE_LP]              =  fe_code_rate_name,
+       [DTV_CODE_RATE_LP]              = fe_code_rate_name,
        [DTV_INNER_FEC]                 = fe_code_rate_name,
        [DTV_ISDBT_LAYERA_FEC]          = fe_code_rate_name,
        [DTV_ISDBT_LAYERB_FEC]          = fe_code_rate_name,
@@ -171,4 +171,4 @@ const void *dvbv5_attr_names[] = {
        [DTV_PILOT]                     = fe_pilot_name,
        [DTV_ROLLOFF]                   = fe_rolloff_name,
        [DTV_DELIVERY_SYSTEM]           = delivery_system_name,
-};
\ No newline at end of file
+};
index 6a384a0..6ba6730 100644 (file)
@@ -53,7 +53,7 @@ struct fe_status_name {
        { FE_TIMEDOUT,    "TIMEDOUT" },
 };
 
-const char *fe_code_rate_name[12] = {
+const char *fe_code_rate_name[13] = {
        [FEC_1_2] =  "1/2",
        [FEC_2_3] =  "2/3",
        [FEC_3_4] =  "3/4",
@@ -66,9 +66,10 @@ const char *fe_code_rate_name[12] = {
        [FEC_9_10] = "9/10",
        [FEC_AUTO] = "AUTO",
        [FEC_NONE] = "NONE",
+       [12] = NULL,
 };
 
-const char *fe_modulation_name[13] = {
+const char *fe_modulation_name[14] = {
        [APSK_16] =  "APSK/16",
        [APSK_32] =  "APSK/32",
        [DQPSK] =    "DQPSK",
@@ -82,9 +83,10 @@ const char *fe_modulation_name[13] = {
        [QPSK] =     "QPSK",
        [VSB_8] =    "VSB/8",
        [VSB_16] =   "VSB/16",
+       [13] = NULL,
 };
 
-const char *fe_transmission_mode_name[7] = {
+const char *fe_transmission_mode_name[8] = {
        [TRANSMISSION_MODE_1K] =   "1K",
        [TRANSMISSION_MODE_2K] =   "2K",
        [TRANSMISSION_MODE_4K] =   "4K",
@@ -92,9 +94,10 @@ const char *fe_transmission_mode_name[7] = {
        [TRANSMISSION_MODE_16K] =  "16K",
        [TRANSMISSION_MODE_32K] =  "32K",
        [TRANSMISSION_MODE_AUTO] = "AUTO",
+       [7] = NULL,
 };
 
-const unsigned fe_bandwidth_name[7] = {
+const unsigned fe_bandwidth_name[8] = {
        [BANDWIDTH_1_712_MHZ] = 1712000,
        [BANDWIDTH_5_MHZ] =     5000000,
        [BANDWIDTH_6_MHZ] =     6000000,
@@ -102,9 +105,10 @@ const unsigned fe_bandwidth_name[7] = {
        [BANDWIDTH_8_MHZ] =     8000000,
        [BANDWIDTH_10_MHZ] =    10000000,
        [BANDWIDTH_AUTO] =      0,
+       [7] = 0,
 };
 
-const char *fe_guard_interval_name[8] = {
+const char *fe_guard_interval_name[9] = {
        [GUARD_INTERVAL_1_4] =    "1/4",
        [GUARD_INTERVAL_1_8] =    "1/8",
        [GUARD_INTERVAL_1_16] =   "1/16",
@@ -113,47 +117,54 @@ const char *fe_guard_interval_name[8] = {
        [GUARD_INTERVAL_19_128] = "19/128",
        [GUARD_INTERVAL_19_256] = "19/256",
        [GUARD_INTERVAL_AUTO] =   "AUTO",
+       [8] = NULL,
 };
 
-const char *fe_hierarchy_name[5] = {
+const char *fe_hierarchy_name[6] = {
        [HIERARCHY_1] =    "1",
        [HIERARCHY_2] =    "2",
        [HIERARCHY_4] =    "4",
        [HIERARCHY_AUTO] = "AUTO",
        [HIERARCHY_NONE] = "NONE",
+       [5] = NULL,
 };
 
-const char *fe_voltage_name[3] = {
+const char *fe_voltage_name[4] = {
        [SEC_VOLTAGE_13] =  "13",
        [SEC_VOLTAGE_18] =  "18",
        [SEC_VOLTAGE_OFF] = "OFF",
+       [3] = NULL,
 };
 
-const char *fe_tone_name[2] = {
+const char *fe_tone_name[3] = {
        [SEC_TONE_OFF] = "OFF",
        [SEC_TONE_ON] =  "ON",
+       [2] = NULL,
 };
 
-const char *fe_inversion_name[3] = {
+const char *fe_inversion_name[4] = {
        [INVERSION_AUTO] = "AUTO",
        [INVERSION_OFF] =  "OFF",
        [INVERSION_ON] =   "ON",
+       [3] = NULL,
 };
 
-const char *fe_pilot_name[3] = {
+const char *fe_pilot_name[4] = {
        [PILOT_AUTO] = "AUTO",
        [PILOT_OFF] =  "OFF",
        [PILOT_ON] =   "ON",
+       [3] = NULL,
 };
 
-const char *fe_rolloff_name[4] = {
+const char *fe_rolloff_name[5] = {
        [ROLLOFF_20] =   "20",
        [ROLLOFF_25] =   "25",
        [ROLLOFF_35] =   "35",
        [ROLLOFF_AUTO] = "AUTO",
+       [4] = NULL,
 };
 
-const char *dvb_v5_name[45] = {
+const char *dvb_v5_name[46] = {
        [DTV_API_VERSION] =                    "API_VERSION",
        [DTV_BANDWIDTH_HZ] =                   "BANDWIDTH_HZ",
        [DTV_CLEAR] =                          "CLEAR",
@@ -199,9 +210,10 @@ const char *dvb_v5_name[45] = {
        [DTV_TUNE] =                           "TUNE",
        [DTV_UNDEFINED] =                      "UNDEFINED",
        [DTV_VOLTAGE] =                        "VOLTAGE",
+       [45] = NULL,
 };
 
-const char *delivery_system_name[19] = {
+const char *delivery_system_name[20] = {
        [SYS_ATSC] =         "ATSC",
        [SYS_ATSCMH] =       "ATSCMH",
        [SYS_CMMB] =         "CMMB",
@@ -221,6 +233,7 @@ const char *delivery_system_name[19] = {
        [SYS_ISDBT] =        "ISDBT",
        [SYS_TURBO] =        "TURBO",
        [SYS_UNDEFINED] =    "UNDEFINED",
+       [19] = NULL,
 };
 
 #endif
index 5a712a7..e3751b4 100644 (file)
@@ -62,7 +62,7 @@ static int exit_after_tuning;
                fprintf(stderr, " (%s)\n", strerror(errno));            \
        } while (0)
 
-static int parse(const char *fname, const char *channel,
+static int parse(const char *fname, int old_format, const char *channel,
                 struct dvb_v5_fe_parms *parms,
                 uint32_t *vpid, uint32_t *apid, uint32_t *sid)
 {
@@ -92,7 +92,10 @@ static int parse(const char *fname, const char *channel,
                return -1;
        }
 
-       dvb_file = parse_format_oneline(fname, ":", sys, zap_formats);
+       if (old_format)
+               dvb_file = parse_format_oneline(fname, ":", sys, zap_formats);
+       else
+               dvb_file = read_dvb_file(fname);
        if (!dvb_file)
                return -2;
 
@@ -318,6 +321,7 @@ static char *usage =
     "     -F        : set up frontend only, don't touch demux\n"
     "     -t number : timeout (seconds)\n"
     "     -o file   : output filename (use -o - for stdout)\n"
+    "     -O        : Channel configuration is using the old format\n"
     "     -h -?     : display this help and exit\n";
 
 int main(int argc, char **argv)
@@ -334,11 +338,12 @@ int main(int argc, char **argv)
        int opt;
        int record = 0;
        int frontend_only = 0;
+       int old_format = 0;
        char *filename = NULL;
        int human_readable = 0, rec_psi = 0;
        struct dvb_v5_fe_parms *parms;
 
-       while ((opt = getopt(argc, argv, "H?hrpxRsFSn:a:f:d:c:t:o:")) != -1) {
+       while ((opt = getopt(argc, argv, "H?hrpxRsFSn:a:f:d:c:t:o:O")) != -1) {
                switch (opt) {
                case 'a':
                        adapter = strtoul(optarg, NULL, 0);
@@ -352,6 +357,9 @@ int main(int argc, char **argv)
                case 't':
                        timeout = strtoul(optarg, NULL, 0);
                        break;
+               case 'O':
+                       old_format++;
+                       break;
                case 'o':
                        filename = strdup(optarg);
                        record = 1;
@@ -420,7 +428,7 @@ int main(int argc, char **argv)
 
        parms = dvb_fe_open(adapter, frontend, !silent, 0);
 
-       if (parse(confname, channel, parms, &vpid, &apid, &sid))
+       if (parse(confname, old_format, channel, parms, &vpid, &apid, &sid))
                return -1;
 
        if (setup_frontend(parms) < 0)
index e4bf8ce..7ed9645 100755 (executable)
@@ -412,7 +412,7 @@ sub output_arrays($$$$)
                printf OUT "struct %s {\n\t\%s idx;\n\tchar *name;\n} %s[%i] = {\n",
                        $name, $type, $name, $size;
        } else {
-               printf OUT "const %s%s[%i] = {\n", $type, $name, $size;
+               printf OUT "const %s%s[%i] = {\n", $type, $name, $size + 1;
        }
 
        foreach my $i (sort keys %$struct) {
@@ -441,6 +441,17 @@ sub output_arrays($$$$)
                        }
                }
        }
+
+       if (!$bitmap) {
+               printf OUT "\t[%s] = ", $size;
+               if ($type eq "char *") {
+                       printf OUT "NULL,\n";
+               } else {
+                       printf OUT "0,\n";
+               }
+       }
+
+
        printf OUT "};\n\n";
 }