diff --git a/docs/html/config_esfilter.html b/docs/html/config_esfilter.html
index f1a7a40b..4cdf15a2 100644
--- a/docs/html/config_esfilter.html
+++ b/docs/html/config_esfilter.html
@@ -67,9 +67,17 @@ The columns have the following functions:
CA Provider
The CA provider to compare. Empty field means any.
+ Stream Index
+ The logical stream index to compare. Note that this index is computed
+ using all filters. Example: If filter is set to AC3 audio type and
+ the language to 'eng' and there are two AC3 'eng' streams in
+ the service, the first stream could be identified using number 1
+ and the second using number 2.
+
PID
Program identification (PID) number to compare. Zero means any.
- This comparison is processed only when service comparison is active.
+ This comparison is processed only when service comparison is active
+ and for the Conditional Access filter.
Action
The rule action defines the operation when all comparisons succeeds.
diff --git a/src/api/api_service.c b/src/api/api_service.c
index e8b847e2..b0d3ec64 100644
--- a/src/api/api_service.c
+++ b/src/api/api_service.c
@@ -93,7 +93,7 @@ api_service_mapper_notify ( void )
}
static htsmsg_t *
-api_service_streams_get_one ( elementary_stream_t *es )
+api_service_streams_get_one ( elementary_stream_t *es, int use_filter )
{
htsmsg_t *e = htsmsg_create_map();
htsmsg_add_u32(e, "index", es->es_index);
@@ -115,6 +115,8 @@ api_service_streams_get_one ( elementary_stream_t *es )
caid_t *ca;
htsmsg_t *e2, *l2 = htsmsg_create_list();
LIST_FOREACH(ca, &es->es_caids, link) {
+ if (use_filter && !ca->use)
+ continue;
e2 = htsmsg_create_map();
htsmsg_add_u32(e2, "caid", ca->caid);
htsmsg_add_u32(e2, "provider", ca->providerid);
@@ -163,12 +165,12 @@ api_service_streams
htsmsg_add_msg(st, NULL, e);
}
TAILQ_FOREACH(es, &s->s_components, es_link)
- htsmsg_add_msg(st, NULL, api_service_streams_get_one(es));
+ htsmsg_add_msg(st, NULL, api_service_streams_get_one(es, 0));
if (TAILQ_FIRST(&s->s_filt_components) == NULL ||
s->s_status == SERVICE_IDLE)
service_build_filter(s);
TAILQ_FOREACH(es, &s->s_filt_components, es_filt_link)
- htsmsg_add_msg(stf, NULL, api_service_streams_get_one(es));
+ htsmsg_add_msg(stf, NULL, api_service_streams_get_one(es, 1));
*resp = htsmsg_create_map();
htsmsg_add_str(*resp, "name", s->s_nicename);
htsmsg_add_msg(*resp, "streams", st);
diff --git a/src/esfilter.c b/src/esfilter.c
index d5de70a6..8a6d8dba 100644
--- a/src/esfilter.c
+++ b/src/esfilter.c
@@ -642,6 +642,12 @@ const idclass_t esfilter_class_video = {
.set = esfilter_class_service_set,
.list = esfilter_class_service_enum,
},
+ {
+ .type = PT_INT,
+ .id = "sindex",
+ .name = "Stream Index",
+ .off = offsetof(esfilter_t, esf_sindex),
+ },
{
.type = PT_INT,
.id = "pid",
@@ -703,6 +709,12 @@ const idclass_t esfilter_class_audio = {
.set = esfilter_class_service_set,
.list = esfilter_class_service_enum,
},
+ {
+ .type = PT_INT,
+ .id = "sindex",
+ .name = "Stream Index",
+ .off = offsetof(esfilter_t, esf_sindex),
+ },
{
.type = PT_INT,
.id = "pid",
@@ -764,6 +776,12 @@ const idclass_t esfilter_class_teletext = {
.set = esfilter_class_service_set,
.list = esfilter_class_service_enum,
},
+ {
+ .type = PT_INT,
+ .id = "sindex",
+ .name = "Stream Index",
+ .off = offsetof(esfilter_t, esf_sindex),
+ },
{
.type = PT_INT,
.id = "pid",
@@ -825,6 +843,12 @@ const idclass_t esfilter_class_subtit = {
.set = esfilter_class_service_set,
.list = esfilter_class_service_enum,
},
+ {
+ .type = PT_INT,
+ .id = "sindex",
+ .name = "Stream Index",
+ .off = offsetof(esfilter_t, esf_sindex),
+ },
{
.type = PT_INT,
.id = "pid",
@@ -894,6 +918,12 @@ const idclass_t esfilter_class_ca = {
.set = esfilter_class_service_set,
.list = esfilter_class_service_enum,
},
+ {
+ .type = PT_INT,
+ .id = "sindex",
+ .name = "Stream Index",
+ .off = offsetof(esfilter_t, esf_sindex),
+ },
{
.type = PT_INT,
.id = "pid",
diff --git a/src/esfilter.h b/src/esfilter.h
index ec681269..f98d30d5 100644
--- a/src/esfilter.h
+++ b/src/esfilter.h
@@ -91,6 +91,7 @@ typedef struct esfilter {
uint32_t esf_type;
char esf_language[4];
char esf_service[UUID_HEX_SIZE];
+ int esf_sindex;
int esf_pid;
uint16_t esf_caid;
uint32_t esf_caprovider;
diff --git a/src/service.c b/src/service.c
index d1d1dcfb..532bf0da 100644
--- a/src/service.c
+++ b/src/service.c
@@ -128,7 +128,7 @@ service_class_channel_enum
static const char *
service_class_get_title ( idnode_t *self )
{
- return service_get_channel_name((service_t*)self);
+ return service_get_full_channel_name((service_t *)self);
}
static const void *
@@ -346,7 +346,7 @@ service_build_filter(service_t *t)
elementary_stream_t *st, *st2, **sta;
esfilter_t *esf;
caid_t *ca, *ca2;
- int i, n, p, o, exclusive;
+ int i, n, p, o, exclusive, sindex;
uint32_t mask;
/* rebuild the filtered and ordered components */
@@ -356,8 +356,11 @@ service_build_filter(service_t *t)
if (!TAILQ_EMPTY(&esfilters[i]))
goto filter;
- TAILQ_FOREACH(st, &t->s_components, es_link)
+ TAILQ_FOREACH(st, &t->s_components, es_link) {
TAILQ_INSERT_TAIL(&t->s_filt_components, st, es_filt_link);
+ LIST_FOREACH(ca, &st->es_caids, link)
+ ca->use = 1;
+ }
return;
filter:
@@ -378,8 +381,11 @@ filter:
mask = esfilterclsmask[i];
if (TAILQ_EMPTY(&esfilters[i])) {
TAILQ_FOREACH(st, &t->s_components, es_link) {
- if ((mask & SCT_MASK(st->es_type)) != 0)
+ if ((mask & SCT_MASK(st->es_type)) != 0) {
service_build_filter_add(t, st, sta, &p);
+ LIST_FOREACH(ca, &st->es_caids, link)
+ ca->use = 1;
+ }
}
continue;
}
@@ -387,6 +393,7 @@ filter:
TAILQ_FOREACH(esf, &esfilters[i], esf_link) {
if (!esf->esf_enabled)
continue;
+ sindex = 0;
TAILQ_FOREACH(st, &t->s_components, es_link) {
if ((mask & SCT_MASK(st->es_type)) == 0)
continue;
@@ -402,6 +409,8 @@ filter:
continue;
}
if (i == ESF_CLASS_CA) {
+ if (esf->esf_pid && esf->esf_pid != st->es_pid)
+ continue;
ca = NULL;
if ((esf->esf_caid != (uint16_t)-1 || esf->esf_caprovider != -1)) {
LIST_FOREACH(ca, &st->es_caids, link) {
@@ -414,9 +423,12 @@ filter:
if (ca == NULL)
continue;
}
+ sindex++;
+ if (esf->esf_sindex && esf->esf_sindex != sindex)
+ continue;
if (esf->esf_log)
- tvhlog(LOG_INFO, "service", "esfilter: %s %03d %05d %04x %06x \"%s\" %s",
- esfilter_class2txt(i), esf->esf_index, st->es_pid,
+ tvhlog(LOG_INFO, "service", "esfilter: %s %03d %03d %05d %04x %06x \"%s\" %s",
+ esfilter_class2txt(i), st->es_index, esf->esf_index, st->es_pid,
esf->esf_caid, esf->esf_caprovider, t->s_nicename,
esfilter_action2txt(esf->esf_action));
switch (esf->esf_action) {
@@ -464,9 +476,12 @@ ca_ignore:
break;
}
} else {
+ sindex++;
+ if (esf->esf_sindex && esf->esf_sindex != sindex)
+ continue;
if (esf->esf_log)
- tvhlog(LOG_INFO, "service", "esfilter: %s %03d %05d %s %s \"%s\" %s",
- esfilter_class2txt(i), esf->esf_index,
+ tvhlog(LOG_INFO, "service", "esfilter: %s %03d %03d %05d %s %s \"%s\" %s",
+ esfilter_class2txt(i), st->es_index, esf->esf_index,
st->es_pid, streaming_component_type2txt(st->es_type),
lang_code_get(st->es_lang), t->s_nicename,
esfilter_action2txt(esf->esf_action));
@@ -841,24 +856,39 @@ service_stream_make_nicename(service_t *t, elementary_stream_t *st)
void
service_make_nicename(service_t *t)
{
- char buf[200];
+ char buf[256], buf2[16];
source_info_t si;
elementary_stream_t *st;
+ char *service_name;
+ int prefidx;
lock_assert(&t->s_stream_mutex);
t->s_setsourceinfo(t, &si);
+ service_name = si.si_service;
+ if (service_name == NULL || si.si_service[0] == '0') {
+ snprintf(buf2, sizeof(buf2), "{PMT:%d}", t->s_pmt_pid);
+ service_name = buf2;
+ }
+
snprintf(buf, sizeof(buf),
- "%s%s%s%s%s",
- si.si_adapter ?: "", si.si_adapter && si.si_mux ? "/" : "",
- si.si_mux ?: "", si.si_mux && si.si_service ? "/" : "",
- si.si_service ?: "");
+ "%s%s%s%s%s%s%s",
+ si.si_adapter ?: "", si.si_adapter && si.si_network ? "/" : "",
+ si.si_network ?: "", si.si_network && si.si_mux ? "/" : "",
+ si.si_mux ?: "", si.si_mux && service_name ? "/" : "",
+ service_name ?: "");
+ prefidx = (si.si_adapter ? strlen(si.si_adapter) : 0) +
+ (si.si_adapter && si.si_network ? 1 : 0) +
+ (si.si_network ? strlen(si.si_network) : 0) +
+ (si.si_network && si.si_mux ? 1 : 0) +
+ (si.si_mux ? strlen(si.si_mux) : 0);
service_source_info_free(&si);
free(t->s_nicename);
t->s_nicename = strdup(buf);
+ t->s_nicename_prefidx = prefidx;
TAILQ_FOREACH(st, &t->s_components, es_link)
service_stream_make_nicename(t, st);
@@ -1466,6 +1496,33 @@ service_get_channel_name ( service_t *s )
return r;
}
+/*
+ * Get full name for channel from service
+ */
+const char *
+service_get_full_channel_name ( service_t *s )
+{
+ static char __thread buf[256];
+ const char *r = NULL;
+ int len;
+
+ if (s->s_channel_name)
+ r = s->s_channel_name(s);
+ if (r == NULL)
+ return s->s_nicename;
+
+ len = s->s_nicename_prefidx;
+ if (len >= sizeof(buf))
+ len = sizeof(buf) - 1;
+ strncpy(buf, s->s_nicename, len);
+ if (len < sizeof(buf) - 1)
+ buf[len++] = '/';
+ buf[len] = '\0';
+ if (len < sizeof(buf))
+ snprintf(buf + len, sizeof(buf) - len, "%s", r);
+ return buf;
+}
+
/*
* Get number for service
*/
diff --git a/src/service.h b/src/service.h
index 54b7f9ff..2361eead 100644
--- a/src/service.h
+++ b/src/service.h
@@ -300,6 +300,7 @@ typedef struct service {
* Name usable for displaying to user
*/
char *s_nicename;
+ int s_nicename_prefidx;
/**
* Teletext...
@@ -553,6 +554,7 @@ void service_save ( service_t *s, htsmsg_t *c );
void sort_elementary_streams(service_t *t);
const char *service_get_channel_name (service_t *s);
+const char *service_get_full_channel_name (service_t *s);
int service_get_channel_number (service_t *s);
#endif // SERVICE_H__