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__