• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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