summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--stream/dvb_tune.c75
-rw-r--r--stream/dvb_tune.h2
-rw-r--r--stream/stream_dvb.c104
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) {