1 /*
2 * Copyright (c) 2011-2012 - Mauro Carvalho Chehab
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License as published by
6 * the Free Software Foundation version 2.1 of the License.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16 * Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
17 *
18 */
19
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <strings.h> /* strcasecmp */
24 #include <unistd.h>
25
26 #include "dvb-fe-priv.h"
27 #include <libdvbv5/dvb-file.h>
28 #include <libdvbv5/dvb-v5-std.h>
29 #include <libdvbv5/dvb-scan.h>
30 #include <libdvbv5/dvb-log.h>
31 #include <libdvbv5/descriptors.h>
32 #include <libdvbv5/nit.h>
33 #include <libdvbv5/sdt.h>
34 #include <libdvbv5/pat.h>
35 #include <libdvbv5/pmt.h>
36 #include <libdvbv5/vct.h>
37 #include <libdvbv5/desc_ts_info.h>
38 #include <libdvbv5/desc_logical_channel.h>
39 #include <libdvbv5/desc_language.h>
40 #include <libdvbv5/desc_network_name.h>
41 #include <libdvbv5/desc_cable_delivery.h>
42 #include <libdvbv5/desc_sat.h>
43 #include <libdvbv5/desc_terrestrial_delivery.h>
44 #include <libdvbv5/desc_service.h>
45 #include <libdvbv5/desc_frequency_list.h>
46 #include <libdvbv5/desc_event_short.h>
47 #include <libdvbv5/desc_event_extended.h>
48 #include <libdvbv5/desc_atsc_service_location.h>
49 #include <libdvbv5/desc_hierarchy.h>
50 #include <libdvbv5/countries.h>
51
52 #include <config.h>
53
54 #ifdef ENABLE_NLS
55 # include <stdio.h>
56 # include <libintl.h>
57 # define _(string) dgettext(LIBDVBV5_DOMAIN, string)
58
59 #else
60 # define _(string) string
61 #endif
62
63 # define N_(string) string
64
dvb_store_entry_prop(struct dvb_entry * entry,uint32_t cmd,uint32_t value)65 int dvb_store_entry_prop(struct dvb_entry *entry,
66 uint32_t cmd, uint32_t value)
67 {
68 int i;
69
70 for (i = 0; i < entry->n_props; i++) {
71 if (cmd == entry->props[i].cmd)
72 break;
73 }
74 if (i == entry->n_props) {
75 if (i == DTV_MAX_COMMAND) {
76 fprintf(stderr, _("Can't add property %s\n"),
77 dvb_v5_name[cmd]);
78 return -1;
79 }
80 entry->n_props++;
81 entry->props[i].cmd = cmd;
82 }
83
84 entry->props[i].u.data = value;
85
86 return 0;
87 }
88
dvb_retrieve_entry_prop(struct dvb_entry * entry,uint32_t cmd,uint32_t * value)89 int dvb_retrieve_entry_prop(struct dvb_entry *entry,
90 uint32_t cmd, uint32_t *value)
91 {
92 int i;
93
94 for (i = 0; i < entry->n_props; i++) {
95 if (cmd == entry->props[i].cmd) {
96 *value = entry->props[i].u.data;
97 return 0;
98 }
99 }
100
101 return -1;
102 }
103
dvbv5_default_value(int cmd)104 static uint32_t dvbv5_default_value(int cmd)
105 {
106 switch (cmd) {
107 case DTV_MODULATION:
108 case DTV_ISDBT_LAYERA_MODULATION:
109 case DTV_ISDBT_LAYERB_MODULATION:
110 case DTV_ISDBT_LAYERC_MODULATION:
111 return QAM_AUTO;
112
113 case DTV_BANDWIDTH_HZ:
114 return 0;
115
116 case DTV_INVERSION:
117 return INVERSION_AUTO;
118
119 case DTV_CODE_RATE_HP:
120 case DTV_CODE_RATE_LP:
121 case DTV_INNER_FEC:
122 case DTV_ISDBT_LAYERA_FEC:
123 case DTV_ISDBT_LAYERB_FEC:
124 case DTV_ISDBT_LAYERC_FEC:
125 return FEC_AUTO;
126
127 case DTV_GUARD_INTERVAL:
128 return GUARD_INTERVAL_AUTO;
129
130 case DTV_TRANSMISSION_MODE:
131 return TRANSMISSION_MODE_AUTO;
132
133 case DTV_HIERARCHY:
134 return HIERARCHY_AUTO;
135
136 case DTV_STREAM_ID:
137 return 0;
138
139 case DTV_ISDBT_LAYER_ENABLED:
140 return 7;
141
142 case DTV_ISDBT_PARTIAL_RECEPTION:
143 return 1;
144
145 case DTV_ISDBT_SOUND_BROADCASTING:
146 case DTV_ISDBT_SB_SUBCHANNEL_ID:
147 case DTV_ISDBT_SB_SEGMENT_IDX:
148 case DTV_ISDBT_SB_SEGMENT_COUNT:
149 return 0;
150
151 case DTV_ISDBT_LAYERA_TIME_INTERLEAVING:
152 case DTV_ISDBT_LAYERB_TIME_INTERLEAVING:
153 case DTV_ISDBT_LAYERC_TIME_INTERLEAVING:
154 return INTERLEAVING_AUTO;
155
156 case DTV_POLARIZATION:
157 return POLARIZATION_OFF;
158
159 case DTV_ISDBT_LAYERA_SEGMENT_COUNT:
160 return (uint32_t)-1;
161
162 case DTV_ROLLOFF:
163 return ROLLOFF_AUTO;
164
165 case DTV_COUNTRY_CODE:
166 return COUNTRY_UNKNOWN;
167
168 default:
169 return (uint32_t)-1;
170 }
171 }
172
adjust_delsys(struct dvb_entry * entry)173 static void adjust_delsys(struct dvb_entry *entry)
174 {
175 uint32_t delsys = SYS_UNDEFINED;
176 const unsigned int *sys_props;
177 int n;
178 uint32_t v;
179
180 dvb_retrieve_entry_prop(entry, DTV_DELIVERY_SYSTEM, &delsys);
181 switch (delsys) {
182 case SYS_ATSC:
183 case SYS_DVBC_ANNEX_B: {
184 uint32_t modulation = VSB_8;
185
186 dvb_retrieve_entry_prop(entry, DTV_MODULATION, &modulation);
187 switch (modulation) {
188 case VSB_8:
189 case VSB_16:
190 delsys = SYS_ATSC;
191 break;
192 default:
193 delsys = SYS_DVBC_ANNEX_B;
194 break;
195 }
196 dvb_store_entry_prop(entry, DTV_DELIVERY_SYSTEM, delsys);
197 break;
198 }
199 } /* switch */
200
201 /* Fill missing mandatory properties with auto values */
202
203 sys_props = dvb_v5_delivery_system[delsys];
204 if (!sys_props)
205 return;
206
207 n = 0;
208 while (sys_props[n]) {
209 if (dvb_retrieve_entry_prop(entry, sys_props[n], &v) == -1) {
210 dvb_store_entry_prop(entry, sys_props[n], dvbv5_default_value(sys_props[n]));
211 }
212 n++;
213 }
214 }
215
216 /*
217 * Generic parse function for all formats each channel is contained into
218 * just one line.
219 */
dvb_parse_format_oneline(const char * fname,uint32_t delsys,const struct dvb_parse_file * parse_file)220 struct dvb_file *dvb_parse_format_oneline(const char *fname,
221 uint32_t delsys,
222 const struct dvb_parse_file *parse_file)
223 {
224 const char *delimiter = parse_file->delimiter;
225 const struct dvb_parse_struct *formats = parse_file->formats;
226 char *buf = NULL, *p;
227 size_t size = 0;
228 int len = 0;
229 int i, j, line = 0;
230 struct dvb_file *dvb_file;
231 FILE *fd;
232 const struct dvb_parse_struct *fmt;
233 struct dvb_entry *entry = NULL;
234 const struct dvb_parse_table *table;
235 char err_msg[80];
236 int has_inversion;
237
238 dvb_file = calloc(sizeof(*dvb_file), 1);
239 if (!dvb_file) {
240 perror(_("Allocating memory for dvb_file"));
241 return NULL;
242 }
243
244 fd = fopen(fname, "r");
245 if (!fd) {
246 perror(fname);
247 free(dvb_file);
248 return NULL;
249 }
250
251 do {
252 len = getline(&buf, &size, fd);
253 if (len <= 0)
254 break;
255 line++;
256
257 p = buf;
258 while (*p == ' ')
259 p++;
260 if (*p == '\n' || *p == '#' || *p == '\a' || *p == '\0')
261 continue;
262
263 if (parse_file->has_delsys_id) {
264 p = strtok(p, delimiter);
265 if (!p) {
266 sprintf(err_msg, _("unknown delivery system type for %s"),
267 p);
268 goto error;
269 }
270
271 /* Parse the type of the delivery system */
272 for (i = 0; formats[i].id != NULL; i++) {
273 if (!strcmp(p, formats[i].id))
274 break;
275 }
276 if (!formats[i].id) {
277 sprintf(err_msg, _("Doesn't know how to handle delimiter '%s'"),
278 p);
279 goto error;
280 }
281 } else {
282 /* Seek for the delivery system */
283 for (i = 0; formats[i].delsys != 0; i++) {
284 if (formats[i].delsys == delsys)
285 break;
286 }
287 if (!formats[i].delsys) {
288 sprintf(err_msg, _("Doesn't know how to parse delivery system %d"),
289 delsys);
290 goto error;
291 }
292 }
293
294
295 fmt = &formats[i];
296 if (!entry) {
297 dvb_file->first_entry = calloc(sizeof(*entry), 1);
298 entry = dvb_file->first_entry;
299 } else {
300 entry->next = calloc(sizeof(*entry), 1);
301 entry = entry->next;
302 }
303 entry->sat_number = -1;
304 entry->props[entry->n_props].cmd = DTV_DELIVERY_SYSTEM;
305 entry->props[entry->n_props++].u.data = fmt->delsys;
306 has_inversion = 0;
307 for (i = 0; i < fmt->size; i++) {
308 table = &fmt->table[i];
309 if (delsys && !i) {
310 p = strtok(p, delimiter);
311 } else
312 p = strtok(NULL, delimiter);
313 if (p && *p == '#')
314 p = NULL;
315 if (!p && !fmt->table[i].has_default_value) {
316 sprintf(err_msg, _("parameter %i (%s) missing"),
317 i, dvb_cmd_name(table->prop));
318 goto error;
319 }
320 if (p && table->size) {
321 for (j = 0; j < table->size; j++)
322 if (!table->table[j] || !strcasecmp(table->table[j], p))
323 break;
324 if (j == table->size) {
325 sprintf(err_msg, _("parameter %s invalid: %s"),
326 dvb_cmd_name(table->prop), p);
327 goto error;
328 }
329 if (table->prop == DTV_BANDWIDTH_HZ)
330 j = fe_bandwidth_name[j];
331 entry->props[entry->n_props].cmd = table->prop;
332 entry->props[entry->n_props++].u.data = j;
333 } else {
334 long v;
335
336 if (!p)
337 v = fmt->table[i].default_value;
338 else
339 v = atol(p);
340
341 if (table->mult_factor)
342 v *= table->mult_factor;
343
344 switch (table->prop) {
345 case DTV_VIDEO_PID:
346 entry->video_pid = calloc(sizeof(*entry->video_pid), 1);
347 entry->video_pid_len = 1;
348 entry->video_pid[0] = v;
349 break;
350 case DTV_AUDIO_PID:
351 entry->audio_pid = calloc(sizeof(*entry->audio_pid), 1);
352 entry->audio_pid_len = 1;
353 entry->audio_pid[0] = v;
354 break;
355 case DTV_SERVICE_ID:
356 entry->service_id = v;
357 break;
358 case DTV_CH_NAME:
359 entry->channel = calloc(strlen(p) + 1, 1);
360 strcpy(entry->channel, p);
361 break;
362 default:
363 entry->props[entry->n_props].cmd = table->prop;
364 entry->props[entry->n_props++].u.data = v;
365 }
366 }
367 if (table->prop == DTV_INVERSION)
368 has_inversion = 1;
369 }
370 if (!has_inversion) {
371 entry->props[entry->n_props].cmd = DTV_INVERSION;
372 entry->props[entry->n_props++].u.data = INVERSION_AUTO;
373 }
374 adjust_delsys(entry);
375 } while (1);
376 fclose(fd);
377 if (buf)
378 free(buf);
379 return dvb_file;
380
381 error:
382 fprintf (stderr, _("ERROR %s while parsing line %d of %s\n"),
383 err_msg, line, fname);
384 dvb_file_free(dvb_file);
385 fclose(fd);
386 if (buf)
387 free(buf);
388 return NULL;
389 }
390
get_compat_format(uint32_t delivery_system)391 static uint32_t get_compat_format(uint32_t delivery_system)
392 {
393 switch (delivery_system) {
394 case SYS_DVBS:
395 case SYS_DVBS2:
396 case SYS_TURBO:
397 case SYS_ISDBS:
398 case SYS_DSS:
399 return SYS_DVBS;
400 case SYS_ATSC:
401 case SYS_DVBC_ANNEX_B:
402 return SYS_ATSC;
403 case SYS_DVBC_ANNEX_A:
404 case SYS_DVBC_ANNEX_C:
405 return SYS_DVBC_ANNEX_A;
406 case SYS_CMMB:
407 case SYS_ISDBT:
408 case SYS_DVBT:
409 case SYS_DVBT2:
410 case SYS_DTMB:
411 return SYS_DVBT;
412 default:
413 return 0;
414
415 }
416 }
417
dvb_write_format_oneline(const char * fname,struct dvb_file * dvb_file,uint32_t delsys,const struct dvb_parse_file * parse_file)418 int dvb_write_format_oneline(const char *fname,
419 struct dvb_file *dvb_file,
420 uint32_t delsys,
421 const struct dvb_parse_file *parse_file)
422 {
423 const char delimiter = parse_file->delimiter[0];
424 const struct dvb_parse_struct *formats = parse_file->formats;
425 int i, j, line = 0, first;
426 FILE *fp;
427 const struct dvb_parse_struct *fmt;
428 struct dvb_entry *entry;
429 const struct dvb_parse_table *table;
430 uint32_t data;
431 char err_msg[80];
432 uint32_t delsys_compat = 0;
433
434 fp = fopen(fname, "w");
435 if (!fp) {
436 perror(fname);
437 return -errno;
438 }
439
440 for (entry = dvb_file->first_entry; entry != NULL; entry = entry->next) {
441 for (i = 0; i < entry->n_props; i++) {
442 if (entry->props[i].cmd == DTV_DELIVERY_SYSTEM) {
443 delsys = entry->props[i].u.data;
444 break;
445 }
446 }
447
448 for (i = 0; formats[i].delsys != 0; i++) {
449 if (formats[i].delsys == delsys)
450 break;
451 }
452 if (!formats[i].delsys) {
453 delsys_compat = get_compat_format(delsys);
454 for (i = 0; formats[i].delsys != 0; i++) {
455 if (formats[i].delsys == delsys_compat) {
456 delsys = delsys_compat;
457 break;
458 }
459 }
460 }
461 if (formats[i].delsys == 0) {
462 sprintf(err_msg,
463 _("delivery system %d not supported on this format"),
464 delsys);
465 goto error;
466 }
467 adjust_delsys(entry);
468 if (parse_file->has_delsys_id) {
469 fprintf(fp, "%s", formats[i].id);
470 first = 0;
471 } else
472 first = 1;
473
474 fmt = &formats[i];
475 for (i = 0; i < fmt->size; i++) {
476 table = &fmt->table[i];
477
478 if (first)
479 first = 0;
480 else
481 fprintf(fp, "%c", delimiter);
482
483 for (j = 0; j < entry->n_props; j++)
484 if (entry->props[j].cmd == table->prop)
485 break;
486 if (fmt->table[i].has_default_value &&
487 (j < entry->n_props) &&
488 (fmt->table[i].default_value == entry->props[j].u.data))
489 break;
490 if (table->size && j < entry->n_props) {
491 data = entry->props[j].u.data;
492
493 if (table->prop == DTV_BANDWIDTH_HZ) {
494 for (j = 0; j < ARRAY_SIZE(fe_bandwidth_name); j++) {
495 if (fe_bandwidth_name[j] == data) {
496 data = j;
497 break;
498 }
499 }
500 if (j == ARRAY_SIZE(fe_bandwidth_name))
501 data = BANDWIDTH_AUTO;
502 }
503 if (data >= table->size) {
504 sprintf(err_msg,
505 _("value not supported"));
506 goto error;
507 }
508
509 fprintf(fp, "%s", table->table[data]);
510 } else {
511 switch (table->prop) {
512 case DTV_VIDEO_PID:
513 if (!entry->video_pid) {
514 fprintf(stderr,
515 _("WARNING: missing video PID while parsing entry %d of %s\n"),
516 line, fname);
517 fprintf(fp, "%d",0);
518 } else
519 fprintf(fp, "%d",
520 entry->video_pid[0]);
521 break;
522 case DTV_AUDIO_PID:
523 if (!entry->audio_pid) {
524 fprintf(stderr,
525 _("WARNING: missing audio PID while parsing entry %d of %s\n"),
526 line, fname);
527 fprintf(fp, "%d",0);
528 } else
529 fprintf(fp, "%d",
530 entry->audio_pid[0]);
531 break;
532 case DTV_SERVICE_ID:
533 fprintf(fp, "%d", entry->service_id);
534 break;
535 case DTV_CH_NAME:
536 fprintf(fp, "%s", entry->channel);
537 break;
538 default:
539 if (j >= entry->n_props) {
540 if (fmt->table[i].has_default_value) {
541 data = fmt->table[i].default_value;
542 } else {
543 fprintf(stderr,
544 _("property %s not supported while parsing entry %d of %s\n"),
545 dvb_cmd_name(table->prop),
546 line, fname);
547 data = 0;
548 }
549 } else {
550 data = entry->props[j].u.data;
551
552 fprintf(fp, "%d", data);
553 }
554 break;
555 }
556 }
557 }
558 fprintf(fp, "\n");
559 line++;
560 };
561 fclose (fp);
562 return 0;
563
564 error:
565 fprintf(stderr, _("ERROR: %s while parsing entry %d of %s\n"),
566 err_msg, line, fname);
567 fclose(fp);
568 return -1;
569 }
570
571 #define CHANNEL "CHANNEL"
572
fill_entry(struct dvb_entry * entry,char * key,char * value)573 static int fill_entry(struct dvb_entry *entry, char *key, char *value)
574 {
575 int i, j, len, type = 0;
576 int is_video = 0, is_audio = 0, n_prop;
577 uint16_t *pid = NULL;
578 char *p;
579
580 /* Handle the DVBv5 DTV_foo properties */
581 for (i = 0; i < ARRAY_SIZE(dvb_v5_name); i++) {
582 if (!dvb_v5_name[i])
583 continue;
584 if (!strcasecmp(key, dvb_v5_name[i]))
585 break;
586 }
587 if (i < ARRAY_SIZE(dvb_v5_name)) {
588 const char * const *attr_name = dvb_attr_names(i);
589 n_prop = entry->n_props;
590 entry->props[n_prop].cmd = i;
591 if (!attr_name || !*attr_name)
592 entry->props[n_prop].u.data = atol(value);
593 else {
594 for (j = 0; attr_name[j]; j++)
595 if (!strcasecmp(value, attr_name[j]))
596 break;
597 if (!attr_name[j])
598 return -2;
599 entry->props[n_prop].u.data = j;
600 }
601 entry->n_props++;
602 return 0;
603 }
604
605 /* Handle the other properties */
606
607 if (!strcasecmp(key, "SERVICE_ID")) {
608 entry->service_id = atol(value);
609 return 0;
610 }
611
612 if (!strcasecmp(key, "NETWORK_ID")) {
613 entry->network_id = atol(value);
614 return 0;
615 }
616
617 if (!strcasecmp(key, "TRANSPORT_ID")) {
618 entry->transport_id = atol(value);
619 return 0;
620 }
621
622 if (!strcasecmp(key, "VCHANNEL")) {
623 entry->vchannel = strdup(value);
624 return 0;
625 }
626
627 if (!strcasecmp(key, "SAT_NUMBER")) {
628 entry->sat_number = atol(value);
629 return 0;
630 }
631
632 if (!strcasecmp(key, "FREQ_BPF")) {
633 entry->freq_bpf = atol(value);
634 return 0;
635 }
636
637 if (!strcasecmp(key, "DISEQC_WAIT")) {
638 entry->diseqc_wait = atol(value);
639 return 0;
640 }
641
642 if (!strcasecmp(key, "LNB")) {
643 entry->lnb = strdup(value);
644 return 0;
645 }
646
647 if (!strcasecmp(key, "COUNTRY")) {
648 enum dvb_country_t id = dvb_country_a2_to_id(value);
649 if (id == COUNTRY_UNKNOWN)
650 return -2;
651 dvb_store_entry_prop(entry, DTV_COUNTRY_CODE, id);
652 return 0;
653 }
654
655 if (!strcasecmp(key, "VIDEO_PID"))
656 is_video = 1;
657 else if (!strcasecmp(key, "AUDIO_PID"))
658 is_audio = 1;
659 else if (!strcasecmp(key, "POLARIZATION")) {
660 for (j = 0; j < ARRAY_SIZE(dvb_sat_pol_name); j++)
661 if (dvb_sat_pol_name[j] && !strcasecmp(value, dvb_sat_pol_name[j]))
662 break;
663 if (j == ARRAY_SIZE(dvb_sat_pol_name))
664 return -2;
665 dvb_store_entry_prop(entry, DTV_POLARIZATION, j);
666 return 0;
667 } else if (!strncasecmp(key,"PID_", 4)){
668 type = strtol(&key[4], NULL, 16);
669 if (!type)
670 return 0;
671
672 len = 0;
673
674 p = strtok(value," \t");
675 if (!p)
676 return 0;
677 while (p) {
678 entry->other_el_pid = realloc(entry->other_el_pid,
679 (len + 1) *
680 sizeof (*entry->other_el_pid));
681 entry->other_el_pid[len].type = type;
682 entry->other_el_pid[len].pid = atol(p);
683 p = strtok(NULL, " \t\n");
684 len++;
685 }
686 entry->other_el_pid_len = len;
687 }
688
689 if (!is_video && !is_audio) {
690 int cmd = 0;
691
692 for (i = 0; i < DTV_USER_NAME_SIZE; i++) {
693 cmd = i + DTV_USER_COMMAND_START;
694
695 if (!strcasecmp(key, dvb_user_name[i]))
696 break;
697 }
698
699 /*
700 * If the key is not known, just discard.
701 * This way, it provides forward compatibility with new keys
702 * that may be added in the future.
703 */
704
705 if (i >= DTV_USER_NAME_SIZE)
706 return 0;
707
708 /* FIXME: this works only for integer values */
709 n_prop = entry->n_props;
710 entry->props[n_prop].cmd = cmd;
711 entry->props[n_prop].u.data = atol(value);
712 entry->n_props++;
713
714 return 0;
715 }
716
717 /* Video and audio may have multiple values */
718
719 len = 0;
720
721 p = strtok(value," \t");
722 if (!p)
723 return 0;
724 while (p) {
725 pid = realloc(pid, (len + 1) * sizeof (*pid));
726 pid[len] = atol(p);
727 p = strtok(NULL, " \t\n");
728 len++;
729 }
730
731 if (is_video) {
732 entry->video_pid = pid;
733 entry->video_pid_len = len;
734 } else {
735 entry->audio_pid = pid;
736 entry->audio_pid_len = len;
737 }
738
739 return 0;
740 }
741
742
dvb_read_file(const char * fname)743 struct dvb_file *dvb_read_file(const char *fname)
744 {
745 char *buf = NULL, *p, *key, *value;
746 size_t size = 0;
747 int len = 0;
748 int line = 0, rc;
749 struct dvb_file *dvb_file;
750 FILE *fd;
751 struct dvb_entry *entry = NULL;
752 char err_msg[80];
753
754 dvb_file = calloc(sizeof(*dvb_file), 1);
755 if (!dvb_file) {
756 perror(_("Allocating memory for dvb_file"));
757 return NULL;
758 }
759
760 fd = fopen(fname, "r");
761 if (!fd) {
762 perror(fname);
763 free(dvb_file);
764 return NULL;
765 }
766
767 do {
768 len = getline(&buf, &size, fd);
769 if (len <= 0)
770 break;
771 line++;
772 p = buf;
773 while (*p == ' ' || *p == '\t')
774 p++;
775 if (*p == '\n' || *p == '#' || *p == '\a' || *p == '\0')
776 continue;
777
778 if (*p == '[') {
779 /* NEW Entry */
780 if (!entry) {
781 dvb_file->first_entry = calloc(sizeof(*entry), 1);
782 entry = dvb_file->first_entry;
783 } else {
784 adjust_delsys(entry);
785 entry->next = calloc(sizeof(*entry), 1);
786 entry = entry->next;
787 }
788 entry->sat_number = -1;
789 p++;
790 p = strtok(p, "]");
791 if (!p) {
792 sprintf(err_msg, _("Missing channel group"));
793 goto error;
794 }
795 if (!strcasecmp(p, CHANNEL))
796 p += strlen(CHANNEL);
797 while (*p == ' ' || *p == '\t')
798 p++;
799 if (*p) {
800 entry->channel = calloc(strlen(p) + 1, 1);
801 strcpy(entry->channel, p);
802 }
803 } else {
804 if (!entry) {
805 sprintf(err_msg, _("key/value without a channel group"));
806 goto error;
807 }
808 key = strtok(p, "=");
809 if (!key) {
810 sprintf(err_msg, _("missing key"));
811 goto error;
812 }
813 p = &key[strlen(key) - 1];
814 while ((p > key) && (*(p - 1) == ' ' || *(p - 1) == '\t'))
815 p--;
816 *p = 0;
817 value = strtok(NULL, "\n");
818 if (!value) {
819 sprintf(err_msg, _("missing value"));
820 goto error;
821 }
822 while (*value == ' ' || *value == '\t')
823 value++;
824
825 rc = fill_entry(entry, key, value);
826 if (rc == -2) {
827 sprintf(err_msg, _("value %s is invalid for %s"),
828 value, key);
829 goto error;
830 }
831 }
832 } while (1);
833 if (buf)
834 free(buf);
835 if (entry)
836 adjust_delsys(entry);
837 fclose(fd);
838 return dvb_file;
839
840 error:
841 fprintf (stderr, _("ERROR %s while parsing line %d of %s\n"),
842 err_msg, line, fname);
843 if (buf)
844 free(buf);
845 dvb_file_free(dvb_file);
846 fclose(fd);
847 return NULL;
848 };
849
dvb_write_file(const char * fname,struct dvb_file * dvb_file)850 int dvb_write_file(const char *fname, struct dvb_file *dvb_file)
851 {
852 FILE *fp;
853 int i;
854 struct dvb_entry *entry = dvb_file->first_entry;
855 static const char *off = "OFF";
856
857 fp = fopen(fname, "w");
858 if (!fp) {
859 perror(fname);
860 return -errno;
861 }
862
863 for (entry = dvb_file->first_entry; entry != NULL; entry = entry->next) {
864 adjust_delsys(entry);
865 if (entry->channel) {
866 fprintf(fp, "[%s]\n", entry->channel);
867 if (entry->vchannel)
868 fprintf(fp, "\tVCHANNEL = %s\n", entry->vchannel);
869 } else {
870 fprintf(fp, "[CHANNEL]\n");
871 }
872
873 if (entry->service_id)
874 fprintf(fp, "\tSERVICE_ID = %d\n", entry->service_id);
875
876 if (entry->network_id)
877 fprintf(fp, "\tNETWORK_ID = %d\n", entry->network_id);
878
879 if (entry->transport_id)
880 fprintf(fp, "\tTRANSPORT_ID = %d\n", entry->transport_id);
881
882 if (entry->video_pid_len){
883 fprintf(fp, "\tVIDEO_PID =");
884 for (i = 0; i < entry->video_pid_len; i++)
885 fprintf(fp, " %d", entry->video_pid[i]);
886 fprintf(fp, "\n");
887 }
888
889 if (entry->audio_pid_len) {
890 fprintf(fp, "\tAUDIO_PID =");
891 for (i = 0; i < entry->audio_pid_len; i++)
892 fprintf(fp, " %d", entry->audio_pid[i]);
893 fprintf(fp, "\n");
894 }
895
896 if (entry->other_el_pid_len) {
897 int type = -1;
898 for (i = 0; i < entry->other_el_pid_len; i++) {
899 if (type != entry->other_el_pid[i].type) {
900 type = entry->other_el_pid[i].type;
901 if (i)
902 fprintf(fp, "\n");
903 fprintf(fp, "\tPID_%02x =", type);
904 }
905 fprintf(fp, " %d", entry->other_el_pid[i].pid);
906 }
907 fprintf(fp, "\n");
908 }
909
910 if (entry->sat_number >= 0) {
911 fprintf(fp, "\tSAT_NUMBER = %d\n",
912 entry->sat_number);
913 }
914
915 if (entry->freq_bpf > 0) {
916 fprintf(fp, "\tFREQ_BPF = %d\n",
917 entry->freq_bpf);
918 }
919
920 if (entry->diseqc_wait > 0) {
921 fprintf(fp, "\tDISEQC_WAIT = %d\n",
922 entry->diseqc_wait);
923 }
924 if (entry->lnb)
925 fprintf(fp, "\tLNB = %s\n", entry->lnb);
926
927 for (i = 0; i < entry->n_props; i++) {
928 const char * const *attr_name = dvb_attr_names(entry->props[i].cmd);
929 const char *buf;
930
931 if (attr_name) {
932 int j;
933
934 for (j = 0; j < entry->props[i].u.data; j++) {
935 if (!*attr_name)
936 break;
937 attr_name++;
938 }
939 }
940
941 if (entry->props[i].cmd == DTV_COUNTRY_CODE) {
942 buf = dvb_country_to_2letters(entry->props[i].u.data);
943 attr_name = &buf;
944 }
945
946 switch (entry->props[i].cmd) {
947 /* Handle parameters with optional values */
948 case DTV_PLS_CODE:
949 case DTV_PLS_MODE:
950 if (entry->props[i].u.data == (unsigned)-1)
951 continue;
952 break;
953 case DTV_PILOT:
954 if (entry->props[i].u.data == (unsigned)-1)
955 attr_name = &off;
956 break;
957 }
958
959 if (!attr_name || !*attr_name)
960 fprintf(fp, "\t%s = %u\n",
961 dvb_cmd_name(entry->props[i].cmd),
962 entry->props[i].u.data);
963 else
964 fprintf(fp, "\t%s = %s\n",
965 dvb_cmd_name(entry->props[i].cmd),
966 *attr_name);
967 }
968 fprintf(fp, "\n");
969 }
970 fclose(fp);
971 return 0;
972 };
973
dvb_vchannel(struct dvb_v5_fe_parms_priv * parms,struct dvb_table_nit * nit,uint16_t service_id)974 static char *dvb_vchannel(struct dvb_v5_fe_parms_priv *parms,
975 struct dvb_table_nit *nit, uint16_t service_id)
976 {
977 int i;
978 char *buf;
979
980 if (!nit)
981 return NULL;
982
983 for( struct dvb_desc_logical_channel *desc = (struct dvb_desc_logical_channel *) nit->descriptor; desc; desc = (struct dvb_desc_logical_channel *) desc->next ) \
984 if(desc->type == logical_channel_number_descriptor) {
985 /* FIXME: dvb_desc_find(struct dvb_desc_logical_channel, desc, nit, logical_channel_number_descriptor) ? */
986 struct dvb_desc_logical_channel *d = (void *)desc;
987 size_t len;
988 int r;
989
990 len = d->length / 4;
991 for (i = 0; i < len; i++) {
992 if (service_id == d->lcn[i].service_id) {
993 r = asprintf(&buf, "%d.%d",
994 d->lcn[i].logical_channel_number, i);
995 if (r < 0)
996 dvb_perror("asprintf");
997 return buf;
998 }
999 }
1000 }
1001
1002 dvb_desc_find(struct dvb_desc_ts_info, desc, nit, TS_Information_descriptior) {
1003 const struct dvb_desc_ts_info *d = (const void *) desc;
1004 const struct dvb_desc_ts_info_transmission_type *t;
1005 int r;
1006
1007 t = &d->transmission_type;
1008
1009 for (i = 0; i < t->num_of_service; i++) {
1010 if (d->service_id[i] == service_id) {
1011 r = asprintf(&buf, "%d.%d",
1012 d->remote_control_key_id, i);
1013 if (r < 0)
1014 dvb_perror("asprintf");
1015 return buf;
1016 }
1017 }
1018 }
1019
1020 return NULL;
1021 }
1022
sort_other_el_pid(const void * a_arg,const void * b_arg)1023 static int sort_other_el_pid(const void *a_arg, const void *b_arg)
1024 {
1025 const struct dvb_elementary_pid *a = a_arg, *b = b_arg;
1026 int r;
1027
1028 r = b->type - a->type;
1029 if (r)
1030 return r;
1031
1032 return b->pid - a->pid;
1033 }
1034
1035
get_pmt_descriptors(struct dvb_entry * entry,struct dvb_table_pmt * pmt)1036 static void get_pmt_descriptors(struct dvb_entry *entry,
1037 struct dvb_table_pmt *pmt)
1038 {
1039 int has_ac3 = 0;
1040 int video_len = 0, audio_len = 0, other_len = 0;
1041
1042 dvb_pmt_stream_foreach(stream, pmt) {
1043 uint16_t pid = stream->elementary_pid;
1044
1045 switch(stream->type) {
1046 case 0x01: /* ISO/IEC 11172-2 Video */
1047 case 0x02: /* H.262, ISO/IEC 13818-2 or ISO/IEC 11172-2 video */
1048 case 0x1b: /* H.264 AVC */
1049 case 0x24: /* HEVC */
1050 case 0x42: /* CAVS */
1051 case 0x80: /* MPEG-2 MOTO video */
1052 entry->video_pid = realloc(entry->video_pid,
1053 sizeof(*entry->video_pid) *
1054 (video_len + 1));
1055 entry->video_pid[video_len] = pid;
1056 video_len++;
1057 break;
1058 case 0x03: /* ISO/IEC 11172-3 Audio */
1059 case 0x04: /* ISO/IEC 13818-3 Audio */
1060 case 0x07: /* DTS and DTS-HD Audio */
1061 case 0x0f: /* ISO/IEC 13818-7 Audio with ADTS (AAC) */
1062 case 0x11: /* ISO/IEC 14496-3 Audio with the LATM */
1063 case 0x1c: /* ISO/IEC 14496-3 Audio, without additional transport syntax */
1064 case 0x81: /* A52 */
1065 case 0x84: /* SDDS */
1066 case 0x85: /* DTS on HDMV */
1067 case 0x87: /* E-AC3 */
1068 case 0x8a: /* DTS */
1069 case 0x91: /* A52 VLS */
1070 case 0x94: /* SDDS */
1071 entry->audio_pid = realloc(entry->audio_pid,
1072 sizeof(*entry->audio_pid) *
1073 (audio_len + 1));
1074 entry->audio_pid[audio_len] = pid;
1075 audio_len++;
1076 break;
1077 case 0x05: /* private sections */
1078 case 0x06: /* private data */
1079 /*
1080 * Those can be used by sub-titling, teletext and/or
1081 * DVB AC-3. So, need to seek for the AC-3 descriptors
1082 */
1083 dvb_desc_find(struct dvb_desc_service, desc, stream, AC_3_descriptor)
1084 has_ac3 = 1;
1085
1086 dvb_desc_find(struct dvb_desc_service, desc, stream, enhanced_AC_3_descriptor)
1087 has_ac3 = 1;
1088
1089 if (has_ac3) {
1090 entry->audio_pid = realloc(entry->audio_pid,
1091 sizeof(*entry->audio_pid) *
1092 (audio_len + 1));
1093 entry->audio_pid[audio_len] = pid;
1094 audio_len++;
1095 } else {
1096 entry->other_el_pid = realloc(entry->other_el_pid,
1097 sizeof(*entry->other_el_pid) *
1098 (other_len + 1));
1099 entry->other_el_pid[other_len].type = stream->type;
1100 entry->other_el_pid[other_len].pid = pid;
1101 other_len++;
1102 }
1103 break;
1104 default:
1105 entry->other_el_pid = realloc(entry->other_el_pid,
1106 sizeof(*entry->other_el_pid) *
1107 (other_len + 1));
1108 entry->other_el_pid[other_len].type = stream->type;
1109 entry->other_el_pid[other_len].pid = pid;
1110 other_len++;
1111 break;
1112 }
1113 }
1114
1115 entry->video_pid_len = video_len;
1116 entry->audio_pid_len = audio_len;
1117 entry->other_el_pid_len = other_len;
1118
1119 qsort(entry->other_el_pid, entry->other_el_pid_len,
1120 sizeof(*entry->other_el_pid), sort_other_el_pid);
1121 }
1122
get_program_and_store(struct dvb_v5_fe_parms_priv * parms,struct dvb_file * dvb_file,struct dvb_v5_descriptors * dvb_scan_handler,const uint16_t service_id,const uint16_t network_id,const uint16_t transport_id,char * channel,char * vchannel,int get_detected,int get_nit)1123 static int get_program_and_store(struct dvb_v5_fe_parms_priv *parms,
1124 struct dvb_file *dvb_file,
1125 struct dvb_v5_descriptors *dvb_scan_handler,
1126 const uint16_t service_id,
1127 const uint16_t network_id,
1128 const uint16_t transport_id,
1129 char *channel,
1130 char *vchannel,
1131 int get_detected, int get_nit)
1132 {
1133 struct dvb_entry *entry;
1134 int i, j, r, found = 0;
1135 uint32_t freq = 0;
1136
1137 /* Go to the last entry */
1138
1139 if (dvb_file->first_entry) {
1140 entry = dvb_file->first_entry;
1141 while (entry && entry->next)
1142 entry = entry->next;
1143 }
1144
1145 for (i = 0; i < dvb_scan_handler->num_program; i++) {
1146 if (!dvb_scan_handler->program[i].pmt)
1147 continue;
1148
1149 if (service_id == dvb_scan_handler->program[i].pat_pgm->service_id) {
1150 found = 1;
1151 break;
1152 }
1153 }
1154 if (!found) {
1155 dvb_logwarn(_("Channel %s (service ID %d) not found on PMT. Skipping it."),
1156 channel, service_id);
1157 if (channel)
1158 free(channel);
1159 if (vchannel)
1160 free(vchannel);
1161 return 0;
1162 }
1163
1164 /* Create an entry to store the data */
1165 if (!dvb_file->first_entry) {
1166 dvb_file->first_entry = calloc(sizeof(*entry), 1);
1167 entry = dvb_file->first_entry;
1168 } else {
1169 entry->next = calloc(sizeof(*entry), 1);
1170 entry = entry->next;
1171 }
1172 if (!entry) {
1173 dvb_logerr(_("Not enough memory"));
1174 if (channel)
1175 free(channel);
1176 if (vchannel)
1177 free(vchannel);
1178 return -1;
1179 }
1180
1181 /* Initialize data */
1182 entry->service_id = service_id;
1183 entry->network_id = network_id;
1184 entry->transport_id = transport_id;
1185 entry->vchannel = vchannel;
1186 entry->sat_number = parms->p.sat_number;
1187 entry->freq_bpf = parms->p.freq_bpf;
1188 entry->diseqc_wait = parms->p.diseqc_wait;
1189 if (parms->p.lnb)
1190 entry->lnb = strdup(parms->p.lnb->alias);
1191
1192 /* Get PIDs for each elementary inside the service ID */
1193 get_pmt_descriptors(entry, dvb_scan_handler->program[i].pmt);
1194
1195 /* Copy data from parms */
1196 if (get_detected) {
1197 int rc;
1198 do {
1199 rc = dvb_fe_get_parms(&parms->p);
1200 if (rc == EAGAIN)
1201 usleep(100000);
1202 } while (rc == EAGAIN);
1203 if (rc)
1204 dvb_logerr(_("Couldn't get frontend props"));
1205 }
1206 for (j = 0; j < parms->n_props; j++) {
1207 entry->props[j].cmd = parms->dvb_prop[j].cmd;
1208 entry->props[j].u.data = parms->dvb_prop[j].u.data;
1209
1210 /* [ISDB-S]
1211 * Update DTV_STREAM_ID if it was not specified by a user
1212 * or set to a wrong one.
1213 * In those cases, demod must have selected the first TS_ID.
1214 * The update must be after the above dvb_fe_get_parms() call,
1215 * since a lazy FE driver that does not update stream_id prop
1216 * cache in FE.get_frontend() may overwrite the setting again
1217 * with the initial / user-specified wrong value.
1218 */
1219 if (entry->props[j].cmd == DTV_STREAM_ID
1220 && entry->props[j].u.data == 0
1221 && parms->p.current_sys == SYS_ISDBS)
1222 entry->props[j].u.data = dvb_scan_handler->pat->header.id;
1223
1224 if (!channel && entry->props[j].cmd == DTV_FREQUENCY)
1225 freq = parms->dvb_prop[j].u.data;
1226 }
1227 if (!channel) {
1228 r = asprintf(&channel, "%.2f%cHz#%d", freq / 1000000.,
1229 dvb_fe_is_satellite(parms->p.current_sys) ? 'G' : 'M',
1230 service_id);
1231 if (r < 0)
1232 dvb_perror("asprintf");
1233 dvb_log(_("Storing Service ID %d: '%s'"), service_id, channel);
1234 }
1235 entry->n_props = parms->n_props;
1236 entry->channel = channel;
1237
1238 if (get_nit)
1239 dvb_update_transponders(&parms->p, dvb_scan_handler,
1240 dvb_file->first_entry,
1241 entry);
1242
1243 return 0;
1244 }
1245
1246 /* Service type, according with EN 300 468 V1.3.1 (1998-02) */
1247 static char *sdt_services[256] = {
1248 [0x00 ...0xff] = N_("reserved"),
1249 [0x01] = N_("digital television"),
1250 [0x02] = N_("digital radio"),
1251 [0x03] = N_("Teletext"),
1252 [0x04] = N_("NVOD reference"),
1253 [0x05] = N_("NVOD time-shifted"),
1254 [0x06] = N_("mosaic"),
1255 [0x07] = N_("PAL coded signal"),
1256 [0x08] = N_("SECAM coded signal"),
1257 [0x09] = N_("D/D2-MAC"),
1258 [0x0a] = N_("FM Radio"),
1259 [0x0b] = N_("NTSC coded signal"),
1260 [0x0c] = N_("data broadcast"),
1261 [0x80 ...0xfe] = N_("user defined"),
1262 };
1263
dvb_store_channel(struct dvb_file ** dvb_file,struct dvb_v5_fe_parms * __p,struct dvb_v5_descriptors * dvb_scan_handler,int get_detected,int get_nit)1264 int dvb_store_channel(struct dvb_file **dvb_file,
1265 struct dvb_v5_fe_parms *__p,
1266 struct dvb_v5_descriptors *dvb_scan_handler,
1267 int get_detected, int get_nit)
1268 {
1269 struct dvb_v5_fe_parms_priv *parms = (void *)__p;
1270 int rc;
1271 int num_services = 0;
1272
1273 if (!*dvb_file) {
1274 *dvb_file = calloc(sizeof(**dvb_file), 1);
1275 if (!*dvb_file) {
1276 dvb_perror(_("Allocating memory for dvb_file"));
1277 return -1;
1278 }
1279 }
1280
1281 if (dvb_scan_handler->vct) {
1282 atsc_vct_channel_foreach(d, dvb_scan_handler->vct) {
1283 char *channel = NULL;
1284 char *vchannel = NULL;
1285 char *p = d->short_name;
1286 int r;
1287
1288 while (*p == ' ')
1289 p++;
1290 channel = calloc(1, strlen(p) + 1);
1291 strcpy(channel, p);
1292
1293 r = asprintf(&vchannel, "%d.%d",
1294 d->major_channel_number,
1295 d->minor_channel_number);
1296 if (r < 0)
1297 dvb_perror("asprintf");
1298
1299 if (parms->p.verbose)
1300 dvb_log(_("Virtual channel %s, name = %s"),
1301 vchannel, channel);
1302
1303 rc = get_program_and_store(parms, *dvb_file, dvb_scan_handler,
1304 d->program_number, 0, 0,
1305 channel, vchannel,
1306 get_detected, get_nit);
1307 if (rc < 0)
1308 return rc;
1309 }
1310 if (!dvb_scan_handler->sdt)
1311 return 0;
1312 }
1313
1314 dvb_sdt_service_foreach(service, dvb_scan_handler->sdt) {
1315 char *channel = NULL;
1316 char *vchannel = NULL;
1317 uint16_t network_id = 0, transport_id = 0;
1318 int r;
1319
1320 dvb_desc_find(struct dvb_desc_service, desc, service, service_descriptor) {
1321 if (desc->name) {
1322 char *p = desc->name;
1323
1324 while (*p == ' ')
1325 p++;
1326 channel = calloc(strlen(p) + 1, 1);
1327 strcpy(channel, p);
1328 }
1329 dvb_log(_("Service %s, provider %s: %s"),
1330 desc->name, desc->provider,
1331 _(sdt_services[desc->service_type]));
1332 break;
1333 }
1334
1335 if (!channel) {
1336 r = asprintf(&channel, "#%d", service->service_id);
1337 if (r < 0)
1338 dvb_perror("asprintf");
1339 }
1340
1341 if (parms->p.verbose)
1342 dvb_log(_("Storing as channel %s"), channel);
1343 vchannel = dvb_vchannel(parms, dvb_scan_handler->nit, service->service_id);
1344
1345 if (dvb_scan_handler->nit && dvb_scan_handler->nit->transport) {
1346 network_id = dvb_scan_handler->nit->transport->network_id;
1347 transport_id = dvb_scan_handler->nit->transport->transport_id;
1348 }
1349
1350 rc = get_program_and_store(parms, *dvb_file, dvb_scan_handler,
1351 service->service_id,
1352 network_id,
1353 transport_id,
1354 channel, vchannel,
1355 get_detected, get_nit);
1356 if (rc < 0)
1357 return rc;
1358
1359 num_services++;
1360 }
1361
1362 if (!dvb_scan_handler->sdt || num_services < dvb_scan_handler->num_program) {
1363 int warned = 0;
1364 int i;
1365
1366 for (i = 0; i < dvb_scan_handler->num_program; i++) {
1367 int found = 0;
1368 unsigned service_id;
1369
1370 if (!dvb_scan_handler->program[i].pmt)
1371 continue;
1372
1373 service_id = dvb_scan_handler->program[i].pat_pgm->service_id;
1374 dvb_sdt_service_foreach(service, dvb_scan_handler->sdt) {
1375 if (service->service_id == service_id) {
1376 found = 1;
1377 break;
1378 }
1379 }
1380 if (found)
1381 continue;
1382
1383 if (!warned) {
1384 if (!dvb_scan_handler->sdt)
1385 dvb_log(_("WARNING: no SDT table - storing channel(s) without their names"));
1386 else
1387 dvb_log(_("WARNING: Some Service IDs are not at the SDT table"));
1388 warned = 1;
1389 }
1390
1391 rc = get_program_and_store(parms, *dvb_file, dvb_scan_handler,
1392 service_id, 0, 0,
1393 NULL, NULL,
1394 get_detected, get_nit);
1395 if (rc < 0)
1396 return rc;
1397 }
1398
1399 return 0;
1400 }
1401
1402 return 0;
1403 }
1404
dvb_parse_format(const char * name)1405 enum dvb_file_formats dvb_parse_format(const char *name)
1406 {
1407 if (!strcasecmp(name, "ZAP"))
1408 return FILE_ZAP;
1409 if (!strcasecmp(name, "CHANNEL"))
1410 return FILE_CHANNEL;
1411 if (!strcasecmp(name, "DVBV5"))
1412 return FILE_DVBV5;
1413 if (!strcasecmp(name, "VDR"))
1414 return FILE_VDR;
1415
1416 fprintf(stderr, _("File format %s is unknown\n"), name);
1417 return FILE_UNKNOWN;
1418 }
1419
1420 static struct {
1421 uint32_t delsys;
1422 char *name;
1423 } alt_names[] = {
1424 { SYS_DVBC_ANNEX_A, "DVB-C" },
1425 { SYS_DVBH, "DVB-H" },
1426 { SYS_DVBS, "DVB-S" },
1427 { SYS_DVBS2, "DVB-S2" },
1428 { SYS_DVBT, "DVB-T" },
1429 { SYS_DVBT2, "DVB-T2" },
1430 { SYS_ISDBC, "ISDB-C" },
1431 { SYS_ISDBS, "ISDB-S" },
1432 { SYS_ISDBT, "ISDB-T" },
1433 { SYS_ATSCMH, "ATSC-MH" },
1434 { SYS_DTMB, "DMB-TH" },
1435 { SYS_DTMB, "DMB" },
1436 };
1437
dvb_parse_delsys(const char * name)1438 int dvb_parse_delsys(const char *name)
1439 {
1440 int i, cnt = 0;
1441
1442 /* Check for DVBv5 names */
1443 for (i = 0; i < ARRAY_SIZE(delivery_system_name); i++)
1444 if (delivery_system_name[i] &&
1445 !strcasecmp(name, delivery_system_name[i]))
1446 break;
1447 if (i < ARRAY_SIZE(delivery_system_name))
1448 return i;
1449
1450 /* Also accept the alternative names */
1451 for (i = 0; i < ARRAY_SIZE(alt_names); i++)
1452 if (!strcasecmp(name, alt_names[i].name))
1453 break;
1454 if (i < ARRAY_SIZE(alt_names))
1455 return alt_names[i].delsys;
1456
1457 /*
1458 * Not found. Print all possible values, except for
1459 * SYS_UNDEFINED.
1460 */
1461 fprintf(stderr, _("ERROR: Delivery system %s is not known. Valid values are:\n"),
1462 name);
1463 for (i = 0; i < ARRAY_SIZE(alt_names) - 1; i++) {
1464 if (!(cnt % 5))
1465 fprintf(stderr, "\n");
1466 fprintf(stderr, "%-15s", alt_names[i].name);
1467 cnt++;
1468 }
1469
1470 for (i = 1; i < ARRAY_SIZE(delivery_system_name) - 1; i++) {
1471 if (!(cnt % 5))
1472 fprintf(stderr, "\n");
1473 fprintf(stderr, "%-15s", delivery_system_name[i]);
1474 cnt++;
1475 }
1476 if (cnt % 5)
1477 fprintf(stderr, "\n");
1478
1479 fprintf(stderr, "\n");
1480 return -1;
1481 }
1482
dvb_read_file_format(const char * fname,uint32_t delsys,enum dvb_file_formats format)1483 struct dvb_file *dvb_read_file_format(const char *fname,
1484 uint32_t delsys,
1485 enum dvb_file_formats format)
1486 {
1487 struct dvb_file *dvb_file;
1488
1489 switch (format) {
1490 case FILE_CHANNEL: /* DVB channel/transponder old format */
1491 dvb_file = dvb_parse_format_oneline(fname,
1492 SYS_UNDEFINED,
1493 &channel_file_format);
1494 break;
1495 case FILE_ZAP:
1496 dvb_file = dvb_parse_format_oneline(fname,
1497 delsys,
1498 &channel_file_zap_format);
1499 break;
1500 case FILE_DVBV5:
1501 dvb_file = dvb_read_file(fname);
1502 break;
1503 case FILE_VDR:
1504 /* FIXME: add support for VDR input */
1505 fprintf(stderr, _("Currently, VDR format is supported only for output\n"));
1506 return NULL;
1507 default:
1508 fprintf(stderr, _("Format is not supported\n"));
1509 return NULL;
1510 }
1511
1512 return dvb_file;
1513 }
1514
dvb_write_file_format(const char * fname,struct dvb_file * dvb_file,uint32_t delsys,enum dvb_file_formats format)1515 int dvb_write_file_format(const char *fname,
1516 struct dvb_file *dvb_file,
1517 uint32_t delsys,
1518 enum dvb_file_formats format)
1519 {
1520 int ret;
1521
1522 switch (format) {
1523 case FILE_CHANNEL: /* DVB channel/transponder old format */
1524 ret = dvb_write_format_oneline(fname,
1525 dvb_file,
1526 SYS_UNDEFINED,
1527 &channel_file_format);
1528 break;
1529 case FILE_ZAP:
1530 ret = dvb_write_format_oneline(fname,
1531 dvb_file,
1532 delsys,
1533 &channel_file_zap_format);
1534 break;
1535 case FILE_DVBV5:
1536 ret = dvb_write_file(fname, dvb_file);
1537 break;
1538 case FILE_VDR:
1539 ret = dvb_write_format_vdr(fname, dvb_file);
1540 break;
1541 default:
1542 return -1;
1543 }
1544
1545 return ret;
1546 }
1547