static int run_scan(struct arguments *args, struct dvb_v5_fe_parms *parms) { struct dvb_file *dvb_file = NULL, *dvb_file_new = NULL; struct dvb_entry *entry; int i, rc, count = 0, dmx_fd, shift; uint32_t freq, sys; /* This is used only when reading old formats */ switch (parms->current_sys) { case SYS_DVBT: case SYS_DVBS: case SYS_DVBC_ANNEX_A: case SYS_ATSC: sys = parms->current_sys; break; case SYS_DVBC_ANNEX_C: sys = SYS_DVBC_ANNEX_A; break; case SYS_DVBC_ANNEX_B: sys = SYS_ATSC; break; case SYS_ISDBT: sys = SYS_DVBT; break; default: sys = SYS_UNDEFINED; break; } dvb_file = dvb_read_file_format(args->confname, sys, args->input_format); if (!dvb_file) return -2; dmx_fd = open(args->demux_dev, O_RDWR); if (dmx_fd < 0) { perror("openening pat demux failed"); return -3; } for (entry = dvb_file->first_entry; entry != NULL; entry = entry->next) { struct dvb_v5_descriptors *dvb_desc = NULL; /* First of all, set the delivery system */ for (i = 0; i < entry->n_props; i++) if (entry->props[i].cmd == DTV_DELIVERY_SYSTEM) dvb_set_compat_delivery_system(parms, entry->props[i].u.data); /* Copy data into parms */ for (i = 0; i < entry->n_props; i++) { uint32_t data = entry->props[i].u.data; /* Don't change the delivery system */ if (entry->props[i].cmd == DTV_DELIVERY_SYSTEM) continue; dvb_fe_store_parm(parms, entry->props[i].cmd, data); if (parms->current_sys == SYS_ISDBT) { dvb_fe_store_parm(parms, DTV_ISDBT_PARTIAL_RECEPTION, 0); dvb_fe_store_parm(parms, DTV_ISDBT_SOUND_BROADCASTING, 0); dvb_fe_store_parm(parms, DTV_ISDBT_LAYER_ENABLED, 0x07); if (entry->props[i].cmd == DTV_CODE_RATE_HP) { dvb_fe_store_parm(parms, DTV_ISDBT_LAYERA_FEC, data); dvb_fe_store_parm(parms, DTV_ISDBT_LAYERB_FEC, data); dvb_fe_store_parm(parms, DTV_ISDBT_LAYERC_FEC, data); } else if (entry->props[i].cmd == DTV_MODULATION) { dvb_fe_store_parm(parms, DTV_ISDBT_LAYERA_MODULATION, data); dvb_fe_store_parm(parms, DTV_ISDBT_LAYERB_MODULATION, data); dvb_fe_store_parm(parms, DTV_ISDBT_LAYERC_MODULATION, data); } } if (parms->current_sys == SYS_ATSC && entry->props[i].cmd == DTV_MODULATION) { if (data != VSB_8 && data != VSB_16) dvb_fe_store_parm(parms, DTV_DELIVERY_SYSTEM, SYS_DVBC_ANNEX_B); } } /* * If the channel file has duplicated frequencies, or some * entries without any frequency at all, discard. */ freq = 0; for (i = 0; i < entry->n_props; i++) { if (entry->props[i].cmd == DTV_FREQUENCY) { freq = entry->props[i].u.data; break; } } if (!freq) continue; shift = estimate_freq_shift(parms); if (dvb_desc && !new_freq_is_needed(dvb_file->first_entry, entry, freq, dvb_desc->nit_table.pol, shift)) continue; rc = dvb_fe_set_parms(parms); if (rc < 0) { PERROR("dvb_fe_set_parms failed"); return -1; } /* As the DVB core emulates it, better to always use auto */ dvb_fe_store_parm(parms, DTV_INVERSION, INVERSION_AUTO); dvb_fe_retrieve_parm(parms, DTV_FREQUENCY, &freq); count++; dvb_log("Scanning frequency #%d %d", count, freq); if (verbose) dvb_fe_prt_parms(parms); rc = check_frontend(args, parms); if (rc < 0) continue; dvb_desc = dvb_get_ts_tables(parms, dmx_fd, parms->current_sys, args->other_nit, args->timeout_multiply, verbose); if (!dvb_desc) continue; for (i = 0; i < dvb_desc->sdt_table.service_table_len; i++) { struct service_table *service_table = &dvb_desc->sdt_table.service_table[i]; entry->vchannel = dvb_vchannel(dvb_desc, i); printf("Service #%d (%d)", i, service_table->service_id); if (service_table->service_name) printf(" %s", service_table->service_name); if (entry->vchannel) printf(" channel %s", entry->vchannel); printf("\n"); } store_dvb_channel(&dvb_file_new, parms, dvb_desc, args->get_detected, args->get_nit); if (!args->dont_add_new_freqs) add_other_freq_entries(dvb_file, parms, dvb_desc); dvb_free_ts_tables(dvb_desc); } if (dvb_file_new) write_file_format(args->output, dvb_file_new, parms->current_sys, args->output_format); dvb_file_free(dvb_file); if (dvb_file_new) dvb_file_free(dvb_file_new); close(dmx_fd); return 0; }
int store_dvb_channel(struct dvb_file **dvb_file, struct dvb_v5_fe_parms *parms, struct dvb_descriptors *dvb_desc, int get_detected, int get_nit) { struct dvb_entry *entry; int i, j, has_detected = 1; if (!*dvb_file) { *dvb_file = calloc(sizeof(*dvb_file), 1); if (!*dvb_file) { perror("Allocating memory for dvb_file"); return -1; } } /* Go to the last entry */ entry = (*dvb_file)->first_entry; while (entry && entry->next) entry = entry->next; for (i = 0; i < dvb_desc->sdt_table.service_table_len; i++) { struct service_table *service_table = &dvb_desc->sdt_table.service_table[i]; struct pat_table *pat_table = &dvb_desc->pat_table; struct pid_table *pid_table = NULL; if (!entry) { (*dvb_file)->first_entry = calloc(sizeof(*entry), 1); entry = (*dvb_file)->first_entry; } else { entry->next = calloc(sizeof(*entry), 1); entry = entry->next; } if (!entry) { fprintf(stderr, "Not enough memory\n"); return -1; } entry->sat_number = -1; if (service_table->service_name) { entry->channel = calloc(strlen(service_table->service_name) + 1, 1); strcpy(entry->channel, service_table->service_name); } else { asprintf(&entry->channel, "#%d", service_table->service_id); } entry->service_id = service_table->service_id; entry->vchannel = dvb_vchannel(dvb_desc, i); entry->pol = parms->pol; entry->sat_number = parms->sat_number; entry->freq_bpf = parms->freq_bpf; entry->diseqc_wait = parms->diseqc_wait; if (parms->lnb) entry->lnb = strdup(parms->lnb->alias); for (j = 0; j < pat_table->pid_table_len; j++) { pid_table = &pat_table->pid_table[j]; if (service_table->service_id == pid_table->service_id) break; } if (j == pat_table->pid_table_len) { fprintf(stderr, "Service ID %d not found on PMT!\n", service_table->service_id); has_detected = 0; } else has_detected = 1; /* * Video/audio/other pid's can only be filled if the service * was found. */ if (has_detected) { entry->video_pid = calloc(sizeof(*entry[i].video_pid), pid_table->video_pid_len); for (j = 0; j < pid_table->video_pid_len; j++) entry->video_pid[j] = pid_table->video_pid[j]; entry->video_pid_len = pid_table->video_pid_len; entry->audio_pid = calloc(sizeof(*entry[i].audio_pid), pid_table->audio_pid_len); for (j = 0; j < pid_table->audio_pid_len; j++) entry->audio_pid[j] = pid_table->audio_pid[j]; entry->audio_pid_len = pid_table->audio_pid_len; entry->other_el_pid = calloc(sizeof(*entry->other_el_pid), pid_table->other_el_pid_len); memcpy(entry->other_el_pid, pid_table->other_el_pid, pid_table->other_el_pid_len * sizeof(*entry->other_el_pid)); entry->other_el_pid_len = pid_table->other_el_pid_len; qsort(entry->other_el_pid, entry->other_el_pid_len, sizeof(*entry->other_el_pid), sort_other_el_pid); } /* Copy data from parms */ if (get_detected) { int rc; do { rc = dvb_fe_get_parms(parms); if (rc == EAGAIN) usleep(100000); } while (rc == EAGAIN); } for (j = 0; j < parms->n_props; j++) { entry->props[j].cmd = parms->dvb_prop[j].cmd; entry->props[j].u.data = parms->dvb_prop[j].u.data; } entry->n_props = parms->n_props; if (get_nit) handle_std_specific_parms(entry, dvb_desc); } return 0; }