diff options
-rw-r--r-- | stream/dvb_tune.c | 75 | ||||
-rw-r--r-- | stream/dvb_tune.h | 2 | ||||
-rw-r--r-- | stream/stream_dvb.c | 104 |
3 files changed, 122 insertions, 59 deletions
diff --git a/stream/dvb_tune.c b/stream/dvb_tune.c index 7ec4bcd9e8..1f982d6887 100644 --- a/stream/dvb_tune.c +++ b/stream/dvb_tune.c @@ -40,38 +40,93 @@ #include "dvb_tune.h" #include "common/msg.h" -int dvb_get_tuner_type(int fe_fd, struct mp_log *log) +int dvb_get_tuner_types(int fe_fd, struct mp_log *log, int** tuner_types) { +#ifdef DVB_USE_S2API + /* S2API is the DVB API new since 2.6.28. + It allows to query frontends with multiple delivery systems. */ + struct dtv_property p[] = {{ .cmd = DTV_ENUM_DELSYS }}; + struct dtv_properties cmdseq = {.num = 1, .props = p}; + mp_verbose(log, "Querying tuner type via DVBv5 API for frontend FD %d\n", + fe_fd); + if ((ioctl(fe_fd, FE_GET_PROPERTY, &cmdseq)) < -0) { + mp_err(log, "FE_GET_PROPERTY error: %d, FD: %d\n\n", errno, fe_fd); + return 0; + } + int num_tuner_types = p[0].u.buffer.len; + mp_verbose(log, "Number of supported delivery systems: %d\n", num_tuner_types); + if (num_tuner_types == 0) { + mp_err(log, "Frontend FD %d returned no delivery systems!", fe_fd); + return 0; + } + (*tuner_types) = talloc_array(NULL, int, num_tuner_types); + int supported_tuners = 0; + for(;p[0].u.buffer.len > 0; p[0].u.buffer.len--) { + fe_delivery_system_t delsys = p[0].u.buffer.data[p[0].u.buffer.len - 1]; + /* Second level standards like like DVB-T2, DVB-S2 not treated here - + Cards can usually either only do S/T/C or both levels. + DVB-T2 probably needs more implementation details, + DVB-S2 is treated in the DVB-S branch already. */ + switch (delsys) { + case SYS_DVBT: + mp_verbose(log, "TUNER TYPE SEEMS TO BE DVB-T\n"); + (*tuner_types)[supported_tuners++] = TUNER_TER; + break; + case SYS_DVBC_ANNEX_AC: + mp_verbose(log, "TUNER TYPE SEEMS TO BE DVB-C\n"); + (*tuner_types)[supported_tuners++] = TUNER_CBL; + break; + case SYS_DVBS: + mp_verbose(log, "TUNER TYPE SEEMS TO BE DVB-S\n"); + (*tuner_types)[supported_tuners++] = TUNER_SAT; + break; +#ifdef DVB_ATSC + case SYS_ATSC: + mp_verbose(log, "TUNER TYPE SEEMS TO BE DVB-ATSC\n"); + (*tuner_types)[supported_tuners++] = TUNER_ATSC; + break; +#endif + default: + mp_err(log, "UNKNOWN TUNER TYPE\n"); + } + } + return supported_tuners; +#else struct dvb_frontend_info fe_info; int res = ioctl(fe_fd, FE_GET_INFO, &fe_info); if (res < 0) { mp_err(log, "FE_GET_INFO error: %d, FD: %d\n\n", errno, fe_fd); return 0; } - + switch (fe_info.type) { case FE_OFDM: mp_verbose(log, "TUNER TYPE SEEMS TO BE DVB-T\n"); - return TUNER_TER; - + *tuner_types = talloc_array(NULL, int, 1); + (*tuner_types)[0] = TUNER_TER; + return 1; case FE_QPSK: mp_verbose(log, "TUNER TYPE SEEMS TO BE DVB-S\n"); - return TUNER_SAT; - + *tuner_types = talloc_array(NULL, int, 1); + (*tuner_types)[0] = TUNER_SAT; + return 1; case FE_QAM: mp_verbose(log, "TUNER TYPE SEEMS TO BE DVB-C\n"); - return TUNER_CBL; - + *tuner_types = talloc_array(NULL, int, 1); + (*tuner_types)[0] = TUNER_CBL; + return 1; #ifdef DVB_ATSC case FE_ATSC: mp_verbose(log, "TUNER TYPE SEEMS TO BE DVB-ATSC\n"); - return TUNER_ATSC; + *tuner_types = talloc_array(NULL, int, 1); + (*tuner_types)[0] = TUNER_ATSC; + return 1; #endif default: mp_err(log, "UNKNOWN TUNER TYPE\n"); return 0; } - +#endif } int dvb_open_devices(dvb_priv_t *priv, int n, int demux_cnt) diff --git a/stream/dvb_tune.h b/stream/dvb_tune.h index 50c598f810..dafa1175bd 100644 --- a/stream/dvb_tune.h +++ b/stream/dvb_tune.h @@ -23,7 +23,7 @@ struct mp_log; -int dvb_get_tuner_type(int fe_fd, struct mp_log *log); +int dvb_get_tuner_types(int fe_fd, struct mp_log *log, int** tuner_types); int dvb_open_devices(dvb_priv_t *priv, int n, int demux_cnt); int dvb_fix_demuxes(dvb_priv_t *priv, int cnt); int dvb_set_ts_filt(dvb_priv_t *priv, int fd, uint16_t pid, dmx_pes_type_t pestype); diff --git a/stream/stream_dvb.c b/stream/stream_dvb.c index 8bc6c4e200..b5ac6ea17a 100644 --- a/stream/stream_dvb.c +++ b/stream/stream_dvb.c @@ -1046,78 +1046,86 @@ dvb_state_t *dvb_get_state(stream_t *stream) continue; } - type = dvb_get_tuner_type(fd, log); + mp_verbose(log, "Opened device %s, FD: %d\n", filename, fd); + int* tuner_types = NULL; + int num_tuner_types = dvb_get_tuner_types(fd, log, &tuner_types); close(fd); - if (type != TUNER_SAT && type != TUNER_TER && type != TUNER_CBL && - type != TUNER_ATSC) { + mp_verbose(log, "Frontend device %s offers %d supported delivery systems.\n", + filename, num_tuner_types); + for (int num_tuner_type=0; num_tuner_type<num_tuner_types; num_tuner_type++) { + type = tuner_types[num_tuner_type]; + if (type != TUNER_SAT && type != TUNER_TER && type != TUNER_CBL && + type != TUNER_ATSC) { mp_verbose(log, "DVB_CONFIG, can't detect tuner type of " "card %d, skipping\n", i); continue; - } + } - void *talloc_ctx = talloc_new(NULL); - char *conf_file = NULL; - if (priv->cfg_file && priv->cfg_file[0]) + void *talloc_ctx = talloc_new(NULL); + char *conf_file = NULL; + if (priv->cfg_file && priv->cfg_file[0]) conf_file = priv->cfg_file; - else { + else { switch (type) { case TUNER_TER: - conf_file = mp_find_config_file(talloc_ctx, global, - "channels.conf.ter"); - break; + conf_file = mp_find_config_file(talloc_ctx, global, + "channels.conf.ter"); + break; case TUNER_CBL: - conf_file = mp_find_config_file(talloc_ctx, global, - "channels.conf.cbl"); - break; + conf_file = mp_find_config_file(talloc_ctx, global, + "channels.conf.cbl"); + break; case TUNER_SAT: - conf_file = mp_find_config_file(talloc_ctx, global, - "channels.conf.sat"); - break; + conf_file = mp_find_config_file(talloc_ctx, global, + "channels.conf.sat"); + break; case TUNER_ATSC: - conf_file = mp_find_config_file(talloc_ctx, global, - "channels.conf.atsc"); - break; + conf_file = mp_find_config_file(talloc_ctx, global, + "channels.conf.atsc"); + break; } if (conf_file) { - mp_verbose(log, "Ignoring other channels.conf files.\n"); + mp_verbose(log, "Ignoring other channels.conf files.\n"); } else { - conf_file = mp_find_config_file(talloc_ctx, global, - "channels.conf"); + conf_file = mp_find_config_file(talloc_ctx, global, + "channels.conf"); } - } + } - list = dvb_get_channels(log, priv->cfg_full_transponder, conf_file, - type); - talloc_free(talloc_ctx); + list = dvb_get_channels(log, priv->cfg_full_transponder, conf_file, + type); + talloc_free(talloc_ctx); - if (list == NULL) + if (list == NULL) continue; - size = sizeof(dvb_card_config_t) * (state->count + 1); - tmp = realloc(state->cards, size); + size = sizeof(dvb_card_config_t) * (state->count + 1); + tmp = realloc(state->cards, size); - if (tmp == NULL) { - fprintf(stderr, "DVB_CONFIG, can't realloc %d bytes, skipping\n", - size); + if (tmp == NULL) { + mp_err(log, "DVB_CONFIG, can't realloc %d bytes, skipping\n", + size); continue; - } - cards = tmp; + } + cards = tmp; - name = malloc(20); - if (name == NULL) { - fprintf(stderr, "DVB_CONFIG, can't realloc 20 bytes, skipping\n"); + name = malloc(20); + if (name == NULL) { + mp_err(log, "DVB_CONFIG, can't realloc 20 bytes, skipping\n"); continue; - } + } - state->cards = cards; - state->cards[state->count].devno = i; - state->cards[state->count].list = list; - state->cards[state->count].type = type; - snprintf(name, 20, "DVB-%c card n. %d", - type == TUNER_TER ? 'T' : (type == TUNER_CBL ? 'C' : 'S'), - state->count + 1); - state->cards[state->count].name = name; - state->count++; + state->cards = cards; + state->cards[state->count].devno = i; + state->cards[state->count].list = list; + state->cards[state->count].type = type; + snprintf(name, 20, "DVB-%c card n. %d", + type == TUNER_TER ? 'T' : (type == TUNER_CBL ? 'C' : 'S'), + state->count + 1); + state->cards[state->count].name = name; + state->count++; + } + talloc_free(tuner_types); } if (state->count == 0) { |