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_registration_id.h>
46 #include <libdvbv5/desc_frequency_list.h>
47 #include <libdvbv5/desc_event_short.h>
48 #include <libdvbv5/desc_event_extended.h>
49 #include <libdvbv5/desc_atsc_service_location.h>
50 #include <libdvbv5/desc_hierarchy.h>
51 #include <libdvbv5/countries.h>
52
53 #ifdef ENABLE_NLS
54 # include "gettext.h"
55 # include <libintl.h>
56 # define _(string) dgettext(LIBDVBV5_DOMAIN, string)
57
58 #else
59 # define _(string) string
60 #endif
61
62 # define N_(string) string
63
dvb_store_entry_prop(struct dvb_entry * entry,uint32_t cmd,uint32_t value)64 int dvb_store_entry_prop(struct dvb_entry *entry,
65 uint32_t cmd, uint32_t value)
66 {
67 int i;
68
69 for (i = 0; i < entry->n_props; i++) {
70 if (cmd == entry->props[i].cmd)
71 break;
72 }
73 if (i == entry->n_props) {
74 if (i == DTV_MAX_COMMAND) {
75 if (cmd < ARRAY_SIZE(dvb_v5_name))
76 fprintf(stderr, _("Can't add property %s\n"),
77 dvb_v5_name[cmd]);
78 else
79 fprintf(stderr, _("Can't add property %d\n"),
80 cmd);
81 return -1;
82 }
83 entry->n_props++;
84 entry->props[i].cmd = cmd;
85 }
86
87 entry->props[i].u.data = value;
88
89 return 0;
90 }
91
dvb_retrieve_entry_prop(struct dvb_entry * entry,uint32_t cmd,uint32_t * value)92 int dvb_retrieve_entry_prop(struct dvb_entry *entry,
93 uint32_t cmd, uint32_t *value)
94 {
95 int i;
96
97 for (i = 0; i < entry->n_props; i++) {
98 if (cmd == entry->props[i].cmd) {
99 *value = entry->props[i].u.data;
100 return 0;
101 }
102 }
103
104 return -1;
105 }
106
dvbv5_default_value(int cmd)107 static uint32_t dvbv5_default_value(int cmd)
108 {
109 switch (cmd) {
110 case DTV_MODULATION:
111 case DTV_ISDBT_LAYERA_MODULATION:
112 case DTV_ISDBT_LAYERB_MODULATION:
113 case DTV_ISDBT_LAYERC_MODULATION:
114 return QAM_AUTO;
115
116 case DTV_BANDWIDTH_HZ:
117 return 0;
118
119 case DTV_INVERSION:
120 return INVERSION_AUTO;
121
122 case DTV_CODE_RATE_HP:
123 case DTV_CODE_RATE_LP:
124 case DTV_INNER_FEC:
125 case DTV_ISDBT_LAYERA_FEC:
126 case DTV_ISDBT_LAYERB_FEC:
127 case DTV_ISDBT_LAYERC_FEC:
128 return FEC_AUTO;
129
130 case DTV_GUARD_INTERVAL:
131 return GUARD_INTERVAL_AUTO;
132
133 case DTV_TRANSMISSION_MODE:
134 return TRANSMISSION_MODE_AUTO;
135
136 case DTV_HIERARCHY:
137 return HIERARCHY_AUTO;
138
139 case DTV_STREAM_ID:
140 return 0;
141
142 case DTV_ISDBT_LAYER_ENABLED:
143 return 7;
144
145 case DTV_ISDBT_PARTIAL_RECEPTION:
146 return 1;
147
148 case DTV_ISDBT_SOUND_BROADCASTING:
149 case DTV_ISDBT_SB_SUBCHANNEL_ID:
150 case DTV_ISDBT_SB_SEGMENT_IDX:
151 case DTV_ISDBT_SB_SEGMENT_COUNT:
152 return 0;
153
154 case DTV_ISDBT_LAYERA_TIME_INTERLEAVING:
155 case DTV_ISDBT_LAYERB_TIME_INTERLEAVING:
156 case DTV_ISDBT_LAYERC_TIME_INTERLEAVING:
157 return INTERLEAVING_AUTO;
158
159 case DTV_POLARIZATION:
160 return POLARIZATION_OFF;
161
162 case DTV_ISDBT_LAYERA_SEGMENT_COUNT:
163 return (uint32_t)-1;
164
165 case DTV_ROLLOFF:
166 return ROLLOFF_AUTO;
167
168 case DTV_COUNTRY_CODE:
169 return COUNTRY_UNKNOWN;
170
171 default:
172 return (uint32_t)-1;
173 }
174 }
175
adjust_delsys(struct dvb_entry * entry)176 static void adjust_delsys(struct dvb_entry *entry)
177 {
178 uint32_t delsys = SYS_UNDEFINED;
179 const unsigned int *sys_props;
180 int n;
181 uint32_t v;
182
183 dvb_retrieve_entry_prop(entry, DTV_DELIVERY_SYSTEM, &delsys);
184 switch (delsys) {
185 case SYS_ATSC:
186 case SYS_DVBC_ANNEX_B: {
187 uint32_t modulation = VSB_8;
188
189 dvb_retrieve_entry_prop(entry, DTV_MODULATION, &modulation);
190 switch (modulation) {
191 case VSB_8:
192 case VSB_16:
193 delsys = SYS_ATSC;
194 break;
195 default:
196 delsys = SYS_DVBC_ANNEX_B;
197 break;
198 }
199 dvb_store_entry_prop(entry, DTV_DELIVERY_SYSTEM, delsys);
200 break;
201 }
202 } /* switch */
203
204 /* Fill missing mandatory properties with auto values */
205
206 sys_props = dvb_v5_delivery_system[delsys];
207 if (!sys_props)
208 return;
209
210 n = 0;
211 while (sys_props[n]) {
212 if (dvb_retrieve_entry_prop(entry, sys_props[n], &v) == -1) {
213 dvb_store_entry_prop(entry, sys_props[n], dvbv5_default_value(sys_props[n]));
214 }
215 n++;
216 }
217 }
218
219 /*
220 * Generic parse function for all formats each channel is contained into
221 * just one line.
222 */
dvb_parse_format_oneline(const char * fname,uint32_t delsys,const struct dvb_parse_file * parse_file)223 struct dvb_file *dvb_parse_format_oneline(const char *fname,
224 uint32_t delsys,
225 const struct dvb_parse_file *parse_file)
226 {
227 const char *delimiter = parse_file->delimiter;
228 const struct dvb_parse_struct *formats = parse_file->formats;
229 char *buf = NULL, *p;
230 size_t size = 0;
231 int len = 0;
232 int i, j, line = 0;
233 struct dvb_file *dvb_file;
234 FILE *fd;
235 const struct dvb_parse_struct *fmt;
236 struct dvb_entry *entry = NULL;
237 const struct dvb_parse_table *table;
238 char err_msg[80];
239 int has_inversion;
240
241 dvb_file = calloc(sizeof(*dvb_file), 1);
242 if (!dvb_file) {
243 perror(_("Allocating memory for dvb_file"));
244 return NULL;
245 }
246
247 fd = fopen(fname, "r");
248 if (!fd) {
249 perror(fname);
250 free(dvb_file);
251 return NULL;
252 }
253
254 do {
255 len = getline(&buf, &size, fd);
256 if (len <= 0)
257 break;
258 line++;
259
260 p = buf;
261 while (*p == ' ')
262 p++;
263 if (*p == '\n' || *p == '#' || *p == '\a' || *p == '\0')
264 continue;
265
266 if (parse_file->has_delsys_id) {
267 p = strtok(p, delimiter);
268 if (!p) {
269 sprintf(err_msg, _("unknown delivery system type for %s"),
270 p);
271 goto error;
272 }
273
274 /* Parse the type of the delivery system */
275 for (i = 0; formats[i].id != NULL; i++) {
276 if (!strcmp(p, formats[i].id))
277 break;
278 }
279 if (!formats[i].id) {
280 sprintf(err_msg, _("Doesn't know how to handle delimiter '%s'"),
281 p);
282 goto error;
283 }
284 } else {
285 /* Seek for the delivery system */
286 for (i = 0; formats[i].delsys != 0; i++) {
287 if (formats[i].delsys == delsys)
288 break;
289 }
290 if (!formats[i].delsys) {
291 sprintf(err_msg, _("Doesn't know how to parse delivery system %d"),
292 delsys);
293 goto error;
294 }
295 }
296
297
298 fmt = &formats[i];
299 if (!entry) {
300 dvb_file->first_entry = calloc(sizeof(*entry), 1);
301 entry = dvb_file->first_entry;
302 } else {
303 entry->next = calloc(sizeof(*entry), 1);
304 entry = entry->next;
305 }
306 entry->sat_number = -1;
307 entry->props[entry->n_props].cmd = DTV_DELIVERY_SYSTEM;
308 entry->props[entry->n_props++].u.data = fmt->delsys;
309 has_inversion = 0;
310 for (i = 0; i < fmt->size; i++) {
311 table = &fmt->table[i];
312 if (delsys && !i) {
313 p = strtok(p, delimiter);
314 } else
315 p = strtok(NULL, delimiter);
316 if (p && *p == '#')
317 p = NULL;
318 if (!p && !fmt->table[i].has_default_value) {
319 sprintf(err_msg, _("parameter %i (%s) missing"),
320 i, dvb_cmd_name(table->prop));
321 goto error;
322 }
323 if (p && table->size) {
324 for (j = 0; j < table->size; j++)
325 if (!table->table[j] || !strcasecmp(table->table[j], p))
326 break;
327 if (j == table->size) {
328 sprintf(err_msg, _("parameter %s invalid: %s"),
329 dvb_cmd_name(table->prop), p);
330 goto error;
331 }
332 if (table->prop == DTV_BANDWIDTH_HZ)
333 j = fe_bandwidth_name[j];
334 entry->props[entry->n_props].cmd = table->prop;
335 entry->props[entry->n_props++].u.data = j;
336 } else {
337 long v;
338
339 if (!p)
340 v = fmt->table[i].default_value;
341 else
342 v = atol(p);
343
344 if (table->mult_factor)
345 v *= table->mult_factor;
346
347 switch (table->prop) {
348 case DTV_VIDEO_PID:
349 entry->video_pid = calloc(sizeof(*entry->video_pid), 1);
350 entry->video_pid_len = 1;
351 entry->video_pid[0] = v;
352 break;
353 case DTV_AUDIO_PID:
354 entry->audio_pid = calloc(sizeof(*entry->audio_pid), 1);
355 entry->audio_pid_len = 1;
356 entry->audio_pid[0] = v;
357 break;
358 case DTV_SERVICE_ID:
359 entry->service_id = v;
360 break;
361 case DTV_CH_NAME:
362 entry->channel = calloc(strlen(p) + 1, 1);
363 strcpy(entry->channel, p);
364 break;
365 default:
366 entry->props[entry->n_props].cmd = table->prop;
367 entry->props[entry->n_props++].u.data = v;
368 }
369 }
370 if (table->prop == DTV_INVERSION)
371 has_inversion = 1;
372 }
373 if (!has_inversion) {
374 entry->props[entry->n_props].cmd = DTV_INVERSION;
375 entry->props[entry->n_props++].u.data = INVERSION_AUTO;
376 }
377 adjust_delsys(entry);
378 } while (1);
379 fclose(fd);
380 if (buf)
381 free(buf);
382 return dvb_file;
383
384 error:
385 fprintf (stderr, _("ERROR %s while parsing line %d of %s\n"),
386 err_msg, line, fname);
387 dvb_file_free(dvb_file);
388 fclose(fd);
389 if (buf)
390 free(buf);
391 return NULL;
392 }
393
get_compat_format(uint32_t delivery_system)394 static uint32_t get_compat_format(uint32_t delivery_system)
395 {
396 switch (delivery_system) {
397 case SYS_DVBS:
398 case SYS_DVBS2:
399 case SYS_TURBO:
400 case SYS_ISDBS:
401 case SYS_DSS:
402 return SYS_DVBS;
403 case SYS_ATSC:
404 case SYS_DVBC_ANNEX_B:
405 return SYS_ATSC;
406 case SYS_DVBC_ANNEX_A:
407 case SYS_DVBC_ANNEX_C:
408 return SYS_DVBC_ANNEX_A;
409 case SYS_CMMB:
410 case SYS_ISDBT:
411 case SYS_DVBT:
412 case SYS_DVBT2:
413 case SYS_DTMB:
414 return SYS_DVBT;
415 default:
416 return 0;
417
418 }
419 }
420
dvb_write_format_oneline(const char * fname,struct dvb_file * dvb_file,uint32_t delsys,const struct dvb_parse_file * parse_file)421 int dvb_write_format_oneline(const char *fname,
422 struct dvb_file *dvb_file,
423 uint32_t delsys,
424 const struct dvb_parse_file *parse_file)
425 {
426 const char delimiter = parse_file->delimiter[0];
427 const struct dvb_parse_struct *formats = parse_file->formats;
428 int i, j, line = 0, first;
429 FILE *fp;
430 const struct dvb_parse_struct *fmt;
431 struct dvb_entry *entry;
432 const struct dvb_parse_table *table;
433 uint32_t data;
434 char err_msg[80];
435 uint32_t delsys_compat = 0;
436
437 fp = fopen(fname, "w");
438 if (!fp) {
439 perror(fname);
440 return -errno;
441 }
442
443 for (entry = dvb_file->first_entry; entry != NULL; entry = entry->next) {
444 for (i = 0; i < entry->n_props; i++) {
445 if (entry->props[i].cmd == DTV_DELIVERY_SYSTEM) {
446 delsys = entry->props[i].u.data;
447 break;
448 }
449 }
450
451 for (i = 0; formats[i].delsys != 0; i++) {
452 if (formats[i].delsys == delsys)
453 break;
454 }
455 if (!formats[i].delsys) {
456 delsys_compat = get_compat_format(delsys);
457 for (i = 0; formats[i].delsys != 0; i++) {
458 if (formats[i].delsys == delsys_compat) {
459 delsys = delsys_compat;
460 break;
461 }
462 }
463 }
464 if (formats[i].delsys == 0) {
465 sprintf(err_msg,
466 _("delivery system %d not supported on this format"),
467 delsys);
468 goto error;
469 }
470 adjust_delsys(entry);
471 if (parse_file->has_delsys_id) {
472 fprintf(fp, "%s", formats[i].id);
473 first = 0;
474 } else
475 first = 1;
476
477 fmt = &formats[i];
478 for (i = 0; i < fmt->size; i++) {
479 table = &fmt->table[i];
480
481 if (first)
482 first = 0;
483 else
484 fprintf(fp, "%c", delimiter);
485
486 for (j = 0; j < entry->n_props; j++)
487 if (entry->props[j].cmd == table->prop)
488 break;
489 if (fmt->table[i].has_default_value &&
490 (j < entry->n_props) &&
491 (fmt->table[i].default_value == entry->props[j].u.data))
492 break;
493 if (table->size && j < entry->n_props) {
494 data = entry->props[j].u.data;
495
496 if (table->prop == DTV_BANDWIDTH_HZ) {
497 for (j = 0; j < ARRAY_SIZE(fe_bandwidth_name); j++) {
498 if (fe_bandwidth_name[j] == data) {
499 data = j;
500 break;
501 }
502 }
503 if (j == ARRAY_SIZE(fe_bandwidth_name))
504 data = BANDWIDTH_AUTO;
505 }
506 if (data >= table->size) {
507 sprintf(err_msg,
508 _("value not supported"));
509 goto error;
510 }
511
512 fprintf(fp, "%s", table->table[data]);
513 } else {
514 switch (table->prop) {
515 case DTV_VIDEO_PID:
516 if (!entry->video_pid) {
517 fprintf(stderr,
518 _("WARNING: missing video PID while parsing entry %d of %s\n"),
519 line, fname);
520 fprintf(fp, "%d",0);
521 } else
522 fprintf(fp, "%d",
523 entry->video_pid[0]);
524 break;
525 case DTV_AUDIO_PID:
526 if (!entry->audio_pid) {
527 fprintf(stderr,
528 _("WARNING: missing audio PID while parsing entry %d of %s\n"),
529 line, fname);
530 fprintf(fp, "%d",0);
531 } else
532 fprintf(fp, "%d",
533 entry->audio_pid[0]);
534 break;
535 case DTV_SERVICE_ID:
536 fprintf(fp, "%d", entry->service_id);
537 break;
538 case DTV_CH_NAME:
539 fprintf(fp, "%s", entry->channel);
540 break;
541 default:
542 if (j >= entry->n_props) {
543 if (fmt->table[i].has_default_value) {
544 data = fmt->table[i].default_value;
545 } else {
546 fprintf(stderr,
547 _("property %s not supported while parsing entry %d of %s\n"),
548 dvb_cmd_name(table->prop),
549 line, fname);
550 data = 0;
551 }
552 } else {
553 data = entry->props[j].u.data;
554 }
555
556 fprintf(fp, "%d", data);
557 break;
558 }
559 }
560 }
561 fprintf(fp, "\n");
562 line++;
563 };
564 fclose (fp);
565 return 0;
566
567 error:
568 fprintf(stderr, _("ERROR: %s while parsing entry %d of %s\n"),
569 err_msg, line, fname);
570 fclose(fp);
571 return -1;
572 }
573
574 #define CHANNEL "CHANNEL"
575
fill_entry(struct dvb_entry * entry,char * key,char * value)576 static int fill_entry(struct dvb_entry *entry, char *key, char *value)
577 {
578 int i, j, len, type = 0;
579 int is_video = 0, is_audio = 0, n_prop;
580 uint16_t *pid = NULL;
581 char *p;
582
583 /* Handle the DVBv5 DTV_foo properties */
584 for (i = 0; i < ARRAY_SIZE(dvb_v5_name); i++) {
585 if (!dvb_v5_name[i])
586 continue;
587 if (!strcasecmp(key, dvb_v5_name[i]))
588 break;
589 }
590 if (i < ARRAY_SIZE(dvb_v5_name)) {
591 const char * const *attr_name = dvb_attr_names(i);
592 n_prop = entry->n_props;
593 entry->props[n_prop].cmd = i;
594 if (!attr_name || !*attr_name)
595 entry->props[n_prop].u.data = atol(value);
596 else {
597 for (j = 0; attr_name[j]; j++)
598 if (!strcasecmp(value, attr_name[j]))
599 break;
600 if (!attr_name[j])
601 return -2;
602 entry->props[n_prop].u.data = j;
603 }
604 entry->n_props++;
605 return 0;
606 }
607
608 /* Handle the other properties */
609
610 if (!strcasecmp(key, "SERVICE_ID")) {
611 entry->service_id = atol(value);
612 return 0;
613 }
614
615 if (!strcasecmp(key, "NETWORK_ID")) {
616 entry->network_id = atol(value);
617 return 0;
618 }
619
620 if (!strcasecmp(key, "TRANSPORT_ID")) {
621 entry->transport_id = atol(value);
622 return 0;
623 }
624
625 if (!strcasecmp(key, "VCHANNEL")) {
626 entry->vchannel = strdup(value);
627 return 0;
628 }
629
630 if (!strcasecmp(key, "SAT_NUMBER")) {
631 entry->sat_number = atol(value);
632 return 0;
633 }
634
635 if (!strcasecmp(key, "FREQ_BPF")) {
636 entry->freq_bpf = atol(value);
637 return 0;
638 }
639
640 if (!strcasecmp(key, "DISEQC_WAIT")) {
641 entry->diseqc_wait = atol(value);
642 return 0;
643 }
644
645 if (!strcasecmp(key, "LNB")) {
646 entry->lnb = strdup(value);
647 return 0;
648 }
649
650 if (!strcasecmp(key, "COUNTRY")) {
651 enum dvb_country_t id = dvb_country_a2_to_id(value);
652 if (id == COUNTRY_UNKNOWN)
653 return -2;
654 dvb_store_entry_prop(entry, DTV_COUNTRY_CODE, id);
655 return 0;
656 }
657
658 if (!strcasecmp(key, "VIDEO_PID"))
659 is_video = 1;
660 else if (!strcasecmp(key, "AUDIO_PID"))
661 is_audio = 1;
662 else if (!strcasecmp(key, "POLARIZATION")) {
663 for (j = 0; j < ARRAY_SIZE(dvb_sat_pol_name); j++)
664 if (dvb_sat_pol_name[j] && !strcasecmp(value, dvb_sat_pol_name[j]))
665 break;
666 if (j == ARRAY_SIZE(dvb_sat_pol_name))
667 return -2;
668 dvb_store_entry_prop(entry, DTV_POLARIZATION, j);
669 return 0;
670 } else if (!strncasecmp(key,"PID_", 4)){
671 type = strtol(&key[4], NULL, 16);
672 if (!type)
673 return 0;
674
675 p = strtok(value," \t");
676 if (!p)
677 return 0;
678 while (p) {
679 entry->other_el_pid = realloc(entry->other_el_pid,
680 (entry->other_el_pid_len + 1) *
681 sizeof (*entry->other_el_pid));
682 entry->other_el_pid[entry->other_el_pid_len].type = type;
683 entry->other_el_pid[entry->other_el_pid_len].pid = atol(p);
684 p = strtok(NULL, " \t\n");
685 entry->other_el_pid_len++;
686 }
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_descriptor) {
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 enum desc_fourcc_type {
1036 PID_ES_OTHER,
1037 PID_ES_VIDEO,
1038 PID_ES_AUDIO,
1039 };
1040
1041 struct desc_fourcc_type_table {
1042 uint8_t stream_type;
1043 char fourcc[4];
1044 enum desc_fourcc_type type;
1045 };
1046
1047 static const struct desc_fourcc_type_table desc_fourcc[] = {
1048 {
1049 .stream_type = 0x06,
1050 .fourcc = {'E', 'A', 'C', '3'}, /* Enhanced AC-3 */
1051 .type = PID_ES_AUDIO,
1052 }, {
1053 .stream_type = 0x06,
1054 .fourcc = {'A', 'C', '-', '3'}, /* AC-3 */
1055 .type = PID_ES_AUDIO,
1056 }, {
1057 .stream_type = 0x06,
1058 .fourcc = {'D', 'T', 'S', '1'}, /* 512 Bpf */
1059 .type = PID_ES_AUDIO,
1060 }, {
1061 .stream_type = 0x06,
1062 .fourcc = {'D', 'T', 'S', '2'}, /* 1024 Bpf */
1063 .type = PID_ES_AUDIO,
1064 }, {
1065 .stream_type = 0x06,
1066 .fourcc = {'D', 'T', 'S', '3'}, /* 2048 Bpf */
1067 .type = PID_ES_AUDIO,
1068 }, {
1069 .stream_type = 0x06,
1070 .fourcc = {'B', 'S', 'S', 'D'}, /* SMPTE 302m */
1071 .type = PID_ES_AUDIO,
1072 }, {
1073 .stream_type = 0x06,
1074 .fourcc = {'H', 'E', 'V', 'C'}, /* HEVC */
1075 .type = PID_ES_VIDEO,
1076 }, {
1077 .stream_type = 0xea,
1078 .fourcc = {'V', 'C', '-', '1'}, /* SMPTE RP 227 */
1079 .type = PID_ES_VIDEO,
1080 }
1081 };
1082
check_descriptor_type(struct dvb_table_pmt_stream * stream)1083 static enum desc_fourcc_type check_descriptor_type(struct dvb_table_pmt_stream *stream)
1084 {
1085 /*
1086 * As the format_identifier of the registration descriptor uniquely
1087 * identifies the format of the data, check it first, if present.
1088 */
1089 dvb_desc_find(struct dvb_desc_service, desc, stream,
1090 registration_descriptor) {
1091 int i;
1092 struct dvb_desc_registration *d = (void *) desc;
1093
1094 for (i = 0; i < ARRAY_SIZE(desc_fourcc); i++) {
1095 if (desc_fourcc[i].stream_type != stream->type)
1096 continue;
1097
1098 if (memcmp(&d->format_identifier, &desc_fourcc[i].fourcc, 4))
1099 continue;
1100
1101 return desc_fourcc[i].type;
1102 }
1103 }
1104
1105 /* Now check for the stream->type directly */
1106
1107 switch(stream->type) {
1108 case 0x01: /* ISO/IEC 11172-2 Video */
1109 case 0x02: /* H.262, ISO/IEC 13818-2 or ISO/IEC 11172-2 video */
1110 case 0x1b: /* H.264 AVC */
1111 case 0x24: /* HEVC */
1112 case 0x42: /* CAVS */
1113 case 0x80: /* MPEG-2 MOTO video */
1114 return PID_ES_VIDEO;
1115 case 0x03: /* ISO/IEC 11172-3 Audio */
1116 case 0x04: /* ISO/IEC 13818-3 Audio */
1117 case 0x07: /* DTS and DTS-HD Audio */
1118 case 0x0f: /* ISO/IEC 13818-7 Audio with ADTS (AAC) */
1119 case 0x11: /* ISO/IEC 14496-3 Audio with the LATM */
1120 case 0x1c: /* ISO/IEC 14496-3 Audio, without additional transport syntax */
1121 case 0x81: /* A52 */
1122 case 0x84: /* SDDS */
1123 case 0x85: /* DTS on HDMV */
1124 case 0x87: /* E-AC3 */
1125 case 0x8a: /* DTS */
1126 case 0x91: /* A52 VLS */
1127 case 0x94: /* SDDS */
1128 return PID_ES_AUDIO;
1129 case 0x05: /* private sections */
1130 case 0x06: /* private data */
1131 /*
1132 * It is likely that the previous check already
1133 * detected, but just in case, let's check for AC-3
1134 */
1135 dvb_desc_find(struct dvb_desc_service, desc, stream, AC_3_descriptor)
1136 return PID_ES_AUDIO;
1137
1138 dvb_desc_find(struct dvb_desc_service, desc, stream, enhanced_AC_3_descriptor)
1139 return PID_ES_AUDIO;
1140 break;
1141 default:
1142 return PID_ES_OTHER;
1143 }
1144
1145 return PID_ES_OTHER;
1146 }
1147
get_pmt_descriptors(struct dvb_entry * entry,struct dvb_table_pmt * pmt)1148 static void get_pmt_descriptors(struct dvb_entry *entry,
1149 struct dvb_table_pmt *pmt)
1150 {
1151 int video_len = 0, audio_len = 0, other_len = 0;
1152 uint16_t pid;
1153 enum desc_fourcc_type type;
1154
1155 dvb_pmt_stream_foreach(stream, pmt) {
1156 pid = stream->elementary_pid;
1157 type = check_descriptor_type(stream);
1158
1159 switch (type) {
1160 case PID_ES_VIDEO:
1161 entry->video_pid = realloc(entry->video_pid,
1162 sizeof(*entry->video_pid) * (video_len + 1));
1163 entry->video_pid[video_len] = pid;
1164 video_len++;
1165 break;
1166 case PID_ES_AUDIO:
1167 entry->audio_pid = realloc(entry->audio_pid,
1168 sizeof(*entry->audio_pid) * (audio_len + 1));
1169 entry->audio_pid[audio_len] = pid;
1170 audio_len++;
1171 break;
1172 case PID_ES_OTHER:
1173 entry->other_el_pid = realloc(entry->other_el_pid,
1174 sizeof(*entry->other_el_pid) * (other_len + 1));
1175 entry->other_el_pid[other_len].type = stream->type;
1176 entry->other_el_pid[other_len].pid = pid;
1177 other_len++;
1178 break;
1179 }
1180 }
1181
1182 entry->video_pid_len = video_len;
1183 entry->audio_pid_len = audio_len;
1184 entry->other_el_pid_len = other_len;
1185
1186 qsort(entry->other_el_pid, entry->other_el_pid_len,
1187 sizeof(*entry->other_el_pid), sort_other_el_pid);
1188 }
1189
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)1190 static int get_program_and_store(struct dvb_v5_fe_parms_priv *parms,
1191 struct dvb_file *dvb_file,
1192 struct dvb_v5_descriptors *dvb_scan_handler,
1193 const uint16_t service_id,
1194 const uint16_t network_id,
1195 const uint16_t transport_id,
1196 char *channel,
1197 char *vchannel,
1198 int get_detected, int get_nit)
1199 {
1200 struct dvb_entry *entry = NULL;
1201 int i, j, r, found = 0;
1202 uint32_t freq = 0;
1203
1204 /* Go to the last entry */
1205
1206 if (dvb_file->first_entry) {
1207 entry = dvb_file->first_entry;
1208 while (entry && entry->next)
1209 entry = entry->next;
1210 }
1211
1212 for (i = 0; i < dvb_scan_handler->num_program; i++) {
1213 if (!dvb_scan_handler->program[i].pmt)
1214 continue;
1215
1216 if (service_id == dvb_scan_handler->program[i].pat_pgm->service_id) {
1217 found = 1;
1218 break;
1219 }
1220 }
1221 if (!found) {
1222 dvb_logwarn(_("Channel %s (service ID %d) not found on PMT. Skipping it."),
1223 channel, service_id);
1224 if (channel)
1225 free(channel);
1226 if (vchannel)
1227 free(vchannel);
1228 return 0;
1229 }
1230
1231 /* Create an entry to store the data */
1232 if (!dvb_file->first_entry) {
1233 dvb_file->first_entry = calloc(sizeof(*entry), 1);
1234 entry = dvb_file->first_entry;
1235 } else if (entry) {
1236 entry->next = calloc(sizeof(*entry), 1);
1237 entry = entry->next;
1238 }
1239 if (!entry) {
1240 dvb_logerr(_("Not enough memory"));
1241 if (channel)
1242 free(channel);
1243 if (vchannel)
1244 free(vchannel);
1245 return -1;
1246 }
1247
1248 /* Initialize data */
1249 entry->service_id = service_id;
1250 entry->network_id = network_id;
1251 entry->transport_id = transport_id;
1252 entry->vchannel = vchannel;
1253 entry->sat_number = parms->p.sat_number;
1254 entry->freq_bpf = parms->p.freq_bpf;
1255 entry->diseqc_wait = parms->p.diseqc_wait;
1256 if (parms->p.lnb)
1257 entry->lnb = strdup(parms->p.lnb->alias);
1258
1259 /* Get PIDs for each elementary inside the service ID */
1260 get_pmt_descriptors(entry, dvb_scan_handler->program[i].pmt);
1261
1262 /* Copy data from parms */
1263 if (get_detected) {
1264 int rc;
1265 do {
1266 rc = dvb_fe_get_parms(&parms->p);
1267 if (rc == EAGAIN)
1268 usleep(100000);
1269 } while (rc == EAGAIN);
1270 if (rc)
1271 dvb_logerr(_("Couldn't get frontend props"));
1272 }
1273 for (j = 0; j < parms->n_props; j++) {
1274 entry->props[j].cmd = parms->dvb_prop[j].cmd;
1275 entry->props[j].u.data = parms->dvb_prop[j].u.data;
1276
1277 /* [ISDB-S]
1278 * Update DTV_STREAM_ID if it was not specified by a user
1279 * or set to a wrong one.
1280 * In those cases, demod must have selected the first TS_ID.
1281 * The update must be after the above dvb_fe_get_parms() call,
1282 * since a lazy FE driver that does not update stream_id prop
1283 * cache in FE.get_frontend() may overwrite the setting again
1284 * with the initial / user-specified wrong value.
1285 */
1286 if (entry->props[j].cmd == DTV_STREAM_ID
1287 && entry->props[j].u.data == 0
1288 && parms->p.current_sys == SYS_ISDBS)
1289 entry->props[j].u.data = dvb_scan_handler->pat->header.id;
1290
1291 if (!channel && entry->props[j].cmd == DTV_FREQUENCY)
1292 freq = parms->dvb_prop[j].u.data;
1293 }
1294 if (!channel) {
1295 r = asprintf(&channel, "%.2f%cHz#%d", freq / 1000000.,
1296 dvb_fe_is_satellite(parms->p.current_sys) ? 'G' : 'M',
1297 service_id);
1298 if (r < 0)
1299 dvb_perror("asprintf");
1300 dvb_log(_("Storing Service ID %d: '%s'"), service_id, channel);
1301 }
1302 entry->n_props = parms->n_props;
1303 entry->channel = channel;
1304
1305 if (get_nit)
1306 dvb_update_transponders(&parms->p, dvb_scan_handler,
1307 dvb_file->first_entry,
1308 entry);
1309
1310 return 0;
1311 }
1312
1313 /* Service type, according with EN 300 468 V1.3.1 (1998-02) */
1314 static char *sdt_services[256] = {
1315 [0x00 ...0xff] = N_("reserved"),
1316 [0x01] = N_("digital television"),
1317 [0x02] = N_("digital radio"),
1318 [0x03] = N_("Teletext"),
1319 [0x04] = N_("NVOD reference"),
1320 [0x05] = N_("NVOD time-shifted"),
1321 [0x06] = N_("mosaic"),
1322 [0x07] = N_("PAL coded signal"),
1323 [0x08] = N_("SECAM coded signal"),
1324 [0x09] = N_("D/D2-MAC"),
1325 [0x0a] = N_("FM Radio"),
1326 [0x0b] = N_("NTSC coded signal"),
1327 [0x0c] = N_("data broadcast"),
1328 [0x80 ...0xfe] = N_("user defined"),
1329 };
1330
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)1331 int dvb_store_channel(struct dvb_file **dvb_file,
1332 struct dvb_v5_fe_parms *__p,
1333 struct dvb_v5_descriptors *dvb_scan_handler,
1334 int get_detected, int get_nit)
1335 {
1336 struct dvb_v5_fe_parms_priv *parms = (void *)__p;
1337 int rc;
1338 int num_services = 0;
1339
1340 if (!*dvb_file) {
1341 *dvb_file = calloc(sizeof(**dvb_file), 1);
1342 if (!*dvb_file) {
1343 dvb_perror(_("Allocating memory for dvb_file"));
1344 return -1;
1345 }
1346 }
1347
1348 if (dvb_scan_handler->vct) {
1349 atsc_vct_channel_foreach(d, dvb_scan_handler->vct) {
1350 char *channel = NULL;
1351 char *vchannel = NULL;
1352 char *p = d->short_name;
1353 int r;
1354
1355 while (*p == ' ')
1356 p++;
1357 channel = calloc(1, strlen(p) + 1);
1358 strcpy(channel, p);
1359
1360 r = asprintf(&vchannel, "%d.%d",
1361 d->major_channel_number,
1362 d->minor_channel_number);
1363 if (r < 0)
1364 dvb_perror("asprintf");
1365
1366 if (parms->p.verbose)
1367 dvb_log(_("Virtual channel %s, name = %s"),
1368 vchannel, channel);
1369
1370 rc = get_program_and_store(parms, *dvb_file, dvb_scan_handler,
1371 d->program_number, 0, 0,
1372 channel, vchannel,
1373 get_detected, get_nit);
1374 if (rc < 0)
1375 return rc;
1376 }
1377 if (!dvb_scan_handler->sdt)
1378 return 0;
1379 }
1380
1381 dvb_sdt_service_foreach(service, dvb_scan_handler->sdt) {
1382 char *channel = NULL;
1383 char *vchannel = NULL;
1384 uint16_t network_id = 0, transport_id = 0;
1385 int r;
1386
1387 dvb_desc_find(struct dvb_desc_service, desc, service, service_descriptor) {
1388 if (desc->name) {
1389 char *p = desc->name;
1390
1391 while (*p == ' ')
1392 p++;
1393 channel = calloc(strlen(p) + 1, 1);
1394 strcpy(channel, p);
1395 }
1396 dvb_log(_("Service %s, provider %s: %s"),
1397 desc->name, desc->provider,
1398 _(sdt_services[desc->service_type]));
1399 break;
1400 }
1401
1402 if (!channel) {
1403 r = asprintf(&channel, "#%d", service->service_id);
1404 if (r < 0)
1405 dvb_perror("asprintf");
1406 }
1407
1408 if (parms->p.verbose)
1409 dvb_log(_("Storing as channel %s"), channel);
1410 vchannel = dvb_vchannel(parms, dvb_scan_handler->nit, service->service_id);
1411
1412 if (dvb_scan_handler->nit && dvb_scan_handler->nit->transport) {
1413 network_id = dvb_scan_handler->nit->transport->network_id;
1414 transport_id = dvb_scan_handler->nit->transport->transport_id;
1415 }
1416
1417 rc = get_program_and_store(parms, *dvb_file, dvb_scan_handler,
1418 service->service_id,
1419 network_id,
1420 transport_id,
1421 channel, vchannel,
1422 get_detected, get_nit);
1423 if (rc < 0)
1424 return rc;
1425
1426 num_services++;
1427 }
1428
1429 if (!dvb_scan_handler->sdt || num_services < dvb_scan_handler->num_program) {
1430 int warned = 0;
1431 int i;
1432
1433 for (i = 0; i < dvb_scan_handler->num_program; i++) {
1434 int found = 0;
1435 unsigned service_id;
1436
1437 if (!dvb_scan_handler->program[i].pmt)
1438 continue;
1439
1440 service_id = dvb_scan_handler->program[i].pat_pgm->service_id;
1441 dvb_sdt_service_foreach(service, dvb_scan_handler->sdt) {
1442 if (service->service_id == service_id) {
1443 found = 1;
1444 break;
1445 }
1446 }
1447 if (found)
1448 continue;
1449
1450 if (!warned) {
1451 if (!dvb_scan_handler->sdt)
1452 dvb_log(_("WARNING: no SDT table - storing channel(s) without their names"));
1453 else
1454 dvb_log(_("WARNING: Some Service IDs are not at the SDT table"));
1455 warned = 1;
1456 }
1457
1458 rc = get_program_and_store(parms, *dvb_file, dvb_scan_handler,
1459 service_id, 0, 0,
1460 NULL, NULL,
1461 get_detected, get_nit);
1462 if (rc < 0)
1463 return rc;
1464 }
1465
1466 return 0;
1467 }
1468
1469 return 0;
1470 }
1471
dvb_parse_format(const char * name)1472 enum dvb_file_formats dvb_parse_format(const char *name)
1473 {
1474 if (!strcasecmp(name, "ZAP"))
1475 return FILE_ZAP;
1476 if (!strcasecmp(name, "CHANNEL"))
1477 return FILE_CHANNEL;
1478 if (!strcasecmp(name, "DVBV5"))
1479 return FILE_DVBV5;
1480 if (!strcasecmp(name, "VDR"))
1481 return FILE_VDR;
1482
1483 fprintf(stderr, _("File format %s is unknown\n"), name);
1484 return FILE_UNKNOWN;
1485 }
1486
1487 static struct {
1488 uint32_t delsys;
1489 char *name;
1490 } alt_names[] = {
1491 { SYS_DVBC_ANNEX_A, "DVB-C" },
1492 { SYS_DVBH, "DVB-H" },
1493 { SYS_DVBS, "DVB-S" },
1494 { SYS_DVBS2, "DVB-S2" },
1495 { SYS_DVBT, "DVB-T" },
1496 { SYS_DVBT2, "DVB-T2" },
1497 { SYS_ISDBC, "ISDB-C" },
1498 { SYS_ISDBS, "ISDB-S" },
1499 { SYS_ISDBT, "ISDB-T" },
1500 { SYS_ATSCMH, "ATSC-MH" },
1501 { SYS_DTMB, "DMB-TH" },
1502 { SYS_DTMB, "DMB" },
1503 };
1504
dvb_parse_delsys(const char * name)1505 int dvb_parse_delsys(const char *name)
1506 {
1507 int i, cnt = 0;
1508
1509 /* Check for DVBv5 names */
1510 for (i = 0; i < ARRAY_SIZE(delivery_system_name); i++)
1511 if (delivery_system_name[i] &&
1512 !strcasecmp(name, delivery_system_name[i]))
1513 break;
1514 if (i < ARRAY_SIZE(delivery_system_name))
1515 return i;
1516
1517 /* Also accept the alternative names */
1518 for (i = 0; i < ARRAY_SIZE(alt_names); i++)
1519 if (!strcasecmp(name, alt_names[i].name))
1520 break;
1521 if (i < ARRAY_SIZE(alt_names))
1522 return alt_names[i].delsys;
1523
1524 /*
1525 * Not found. Print all possible values, except for
1526 * SYS_UNDEFINED.
1527 */
1528 fprintf(stderr, _("ERROR: Delivery system %s is not known. Valid values are:\n"),
1529 name);
1530 for (i = 0; i < ARRAY_SIZE(alt_names) - 1; i++) {
1531 if (!(cnt % 5))
1532 fprintf(stderr, "\n");
1533 fprintf(stderr, "%-15s", alt_names[i].name);
1534 cnt++;
1535 }
1536
1537 for (i = 1; i < ARRAY_SIZE(delivery_system_name) - 1; i++) {
1538 if (!(cnt % 5))
1539 fprintf(stderr, "\n");
1540 fprintf(stderr, "%-15s", delivery_system_name[i]);
1541 cnt++;
1542 }
1543 if (cnt % 5)
1544 fprintf(stderr, "\n");
1545
1546 fprintf(stderr, "\n");
1547 return -1;
1548 }
1549
dvb_read_file_format(const char * fname,uint32_t delsys,enum dvb_file_formats format)1550 struct dvb_file *dvb_read_file_format(const char *fname,
1551 uint32_t delsys,
1552 enum dvb_file_formats format)
1553 {
1554 struct dvb_file *dvb_file;
1555
1556 switch (format) {
1557 case FILE_CHANNEL: /* DVB channel/transponder old format */
1558 dvb_file = dvb_parse_format_oneline(fname,
1559 SYS_UNDEFINED,
1560 &channel_file_format);
1561 break;
1562 case FILE_ZAP:
1563 dvb_file = dvb_parse_format_oneline(fname,
1564 delsys,
1565 &channel_file_zap_format);
1566 break;
1567 case FILE_DVBV5:
1568 dvb_file = dvb_read_file(fname);
1569 break;
1570 case FILE_VDR:
1571 /* FIXME: add support for VDR input */
1572 fprintf(stderr, _("Currently, VDR format is supported only for output\n"));
1573 return NULL;
1574 default:
1575 fprintf(stderr, _("Format is not supported\n"));
1576 return NULL;
1577 }
1578
1579 return dvb_file;
1580 }
1581
dvb_write_file_format(const char * fname,struct dvb_file * dvb_file,uint32_t delsys,enum dvb_file_formats format)1582 int dvb_write_file_format(const char *fname,
1583 struct dvb_file *dvb_file,
1584 uint32_t delsys,
1585 enum dvb_file_formats format)
1586 {
1587 int ret;
1588
1589 switch (format) {
1590 case FILE_CHANNEL: /* DVB channel/transponder old format */
1591 ret = dvb_write_format_oneline(fname,
1592 dvb_file,
1593 SYS_UNDEFINED,
1594 &channel_file_format);
1595 break;
1596 case FILE_ZAP:
1597 ret = dvb_write_format_oneline(fname,
1598 dvb_file,
1599 delsys,
1600 &channel_file_zap_format);
1601 break;
1602 case FILE_DVBV5:
1603 ret = dvb_write_file(fname, dvb_file);
1604 break;
1605 case FILE_VDR:
1606 ret = dvb_write_format_vdr(fname, dvb_file);
1607 break;
1608 default:
1609 return -1;
1610 }
1611
1612 return ret;
1613 }
1614