From: Jaroslav Kysela Date: Tue, 6 Oct 2015 08:52:13 +0000 (+0200) Subject: IPTV: Add $m $n $w formatters (mux name, service name, start subscription weight... X-Git-Tag: v4.2.1~1987 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=f0c315c42d314b75d513c3918e89d4e72abccbe4;p=thirdparty%2Ftvheadend.git IPTV: Add $m $n $w formatters (mux name, service name, start subscription weight), fixes #2608 --- diff --git a/src/input/mpegts.h b/src/input/mpegts.h index d4ad64b34..25ab51bfa 100644 --- a/src/input/mpegts.h +++ b/src/input/mpegts.h @@ -604,6 +604,7 @@ struct mpegts_mux_instance mpegts_mux_t *mmi_mux; mpegts_input_t *mmi_input; + int mmi_start_weight; int mmi_tune_failed; }; diff --git a/src/input/mpegts/iptv/iptv.c b/src/input/mpegts/iptv/iptv.c index 0225cecd4..63865235c 100644 --- a/src/input/mpegts/iptv/iptv.c +++ b/src/input/mpegts/iptv/iptv.c @@ -21,6 +21,7 @@ #include "tvhpoll.h" #include "tcp.h" #include "settings.h" +#include "htsstr.h" #include #include @@ -198,13 +199,57 @@ iptv_input_warm_mux ( mpegts_input_t *mi, mpegts_mux_instance_t *mmi ) return 0; } +static const char * +iptv_sub_url_encode(iptv_mux_t *im, const char *s, char *tmp, size_t tmplen) +{ + char *p; + if (im->mm_iptv_url && !strncmp(im->mm_iptv_url, "pipe://", 7)) + return s; + p = url_encode(s); + strncpy(tmp, p, tmplen-1); + tmp[tmplen-1] = '\0'; + free(p); + return tmp; +} + +static const char * +iptv_sub_mux_name(const char *id, const void *aux, char *tmp, size_t tmplen) +{ + const mpegts_mux_instance_t *mmi = aux; + iptv_mux_t *im = (iptv_mux_t*)mmi->mmi_mux; + return iptv_sub_url_encode(im, im->mm_iptv_muxname, tmp, tmplen); +} + +static const char * +iptv_sub_service_name(const char *id, const void *aux, char *tmp, size_t tmplen) +{ + const mpegts_mux_instance_t *mmi = aux; + iptv_mux_t *im = (iptv_mux_t*)mmi->mmi_mux; + return iptv_sub_url_encode(im, im->mm_iptv_svcname, tmp, tmplen); +} + +static const char * +iptv_sub_weight(const char *id, const void *aux, char *tmp, size_t tmplen) +{ + const mpegts_mux_instance_t *mmi = aux; + snprintf(tmp, tmplen, "%d", mmi->mmi_start_weight); + return tmp; +} + +static htsstr_substitute_t iptv_input_subst[] = { + { .id = "m", .getval = iptv_sub_mux_name }, + { .id = "n", .getval = iptv_sub_service_name }, + { .id = "w", .getval = iptv_sub_weight }, + { .id = NULL, .getval = NULL } +}; + static int iptv_input_start_mux ( mpegts_input_t *mi, mpegts_mux_instance_t *mmi ) { int ret = SM_CODE_TUNING_FAILED; iptv_mux_t *im = (iptv_mux_t*)mmi->mmi_mux; iptv_handler_t *ih; - char buf[256]; + char buf[256], rawbuf[512], *raw = im->mm_iptv_url, *s; const char *scheme; url_t url; @@ -212,18 +257,24 @@ iptv_input_start_mux ( mpegts_input_t *mi, mpegts_mux_instance_t *mmi ) if (im->mm_active) return 0; + /* Substitute things */ + if (im->mm_iptv_substitute && raw) { + htsstr_substitute(raw, rawbuf, sizeof(rawbuf), '$', iptv_input_subst, mmi, buf, sizeof(buf)); + raw = rawbuf; + } + /* Parse URL */ mpegts_mux_nice_name((mpegts_mux_t*)im, buf, sizeof(buf)); memset(&url, 0, sizeof(url)); - if (im->mm_iptv_url && !strncmp(im->mm_iptv_url, "pipe://", 7)) { + if (raw && !strncmp(raw, "pipe://", 7)) { scheme = "pipe"; } else { - if (urlparse(im->mm_iptv_url ?: "", &url)) { - tvherror("iptv", "%s - invalid URL [%s]", buf, im->mm_iptv_url); + if (urlparse(raw ?: "", &url)) { + tvherror("iptv", "%s - invalid URL [%s]", buf, raw); return ret; } scheme = url.scheme; @@ -239,9 +290,11 @@ iptv_input_start_mux ( mpegts_input_t *mi, mpegts_mux_instance_t *mmi ) /* Start */ pthread_mutex_lock(&iptv_lock); + s = im->mm_iptv_url_raw; + im->mm_iptv_url_raw = strdup(raw); im->mm_active = mmi; // Note: must set here else mux_started call // will not realise we're ready to accept pid open calls - ret = ih->start(im, im->mm_iptv_url, &url); + ret = ih->start(im, raw, &url); if (!ret) im->im_handler = ih; else @@ -249,6 +302,7 @@ iptv_input_start_mux ( mpegts_input_t *mi, mpegts_mux_instance_t *mmi ) pthread_mutex_unlock(&iptv_lock); urlreset(&url); + free(s); return ret; } diff --git a/src/input/mpegts/iptv/iptv_mux.c b/src/input/mpegts/iptv/iptv_mux.c index a62dbe7dc..7d4cc9210 100644 --- a/src/input/mpegts/iptv/iptv_mux.c +++ b/src/input/mpegts/iptv/iptv_mux.c @@ -129,6 +129,12 @@ const idclass_t iptv_mux_class = .set = iptv_mux_url_set, .opts = PO_MULTILINE }, + { + .type = PT_BOOL, + .id = "iptv_substitute", + .name = N_("Substitute formatters"), + .off = offsetof(iptv_mux_t, mm_iptv_substitute), + }, { .type = PT_STR, .id = "iptv_interface", @@ -202,7 +208,7 @@ iptv_mux_config_save ( mpegts_mux_t *mm ) static void iptv_mux_delete ( mpegts_mux_t *mm, int delconf ) { - char *url, *url_sane, *muxname; + char *url, *url_sane, *url_raw, *muxname; iptv_mux_t *im = (iptv_mux_t*)mm; char ubuf[UUID_HEX_SIZE]; @@ -213,6 +219,7 @@ iptv_mux_delete ( mpegts_mux_t *mm, int delconf ) url = im->mm_iptv_url; // Workaround for silly printing error url_sane = im->mm_iptv_url_sane; + url_raw = im->mm_iptv_url_raw; muxname = im->mm_iptv_muxname; free(im->mm_iptv_interface); free(im->mm_iptv_svcname); @@ -220,6 +227,7 @@ iptv_mux_delete ( mpegts_mux_t *mm, int delconf ) mpegts_mux_delete(mm, delconf); free(url); free(url_sane); + free(url_raw); free(muxname); } diff --git a/src/input/mpegts/iptv/iptv_pipe.c b/src/input/mpegts/iptv/iptv_pipe.c index 409dfa4d5..77eb6e55a 100644 --- a/src/input/mpegts/iptv/iptv_pipe.c +++ b/src/input/mpegts/iptv/iptv_pipe.c @@ -132,8 +132,8 @@ iptv_pipe_read ( iptv_mux_t *im ) pthread_mutex_lock(&global_lock); pthread_mutex_lock(&iptv_lock); if (im->mm_active) { - if (iptv_pipe_start(im, im->mm_iptv_url, NULL)) { - tvherror("iptv", "unable to respawn %s", im->mm_iptv_url); + if (iptv_pipe_start(im, im->mm_iptv_url_raw, NULL)) { + tvherror("iptv", "unable to respawn %s", im->mm_iptv_url_raw); } else { iptv_input_fd_started(im); im->mm_iptv_respawn_last = dispatch_clock; diff --git a/src/input/mpegts/iptv/iptv_private.h b/src/input/mpegts/iptv/iptv_private.h index 809a755fa..289601a58 100644 --- a/src/input/mpegts/iptv/iptv_private.h +++ b/src/input/mpegts/iptv/iptv_private.h @@ -94,8 +94,10 @@ struct iptv_mux udp_connection_t *mm_iptv_connection2; char *mm_iptv_url; char *mm_iptv_url_sane; + char *mm_iptv_url_raw; char *mm_iptv_interface; + int mm_iptv_substitute; int mm_iptv_atsc; char *mm_iptv_muxname; diff --git a/src/input/mpegts/iptv/iptv_rtsp.c b/src/input/mpegts/iptv/iptv_rtsp.c index de5415e84..2c6002b39 100644 --- a/src/input/mpegts/iptv/iptv_rtsp.c +++ b/src/input/mpegts/iptv/iptv_rtsp.c @@ -79,7 +79,7 @@ iptv_rtsp_header ( http_client_t *hc ) } if (hc->hc_code != HTTP_STATUS_OK) { - tvherror("iptv", "invalid error code %d for '%s'", hc->hc_code, im->mm_iptv_url); + tvherror("iptv", "invalid error code %d for '%s'", hc->hc_code, im->mm_iptv_url_raw); return 0; } @@ -126,7 +126,7 @@ iptv_rtsp_data return 0; if (len > 0) - tvherror("iptv", "unknown data %zd received for '%s'", len, im->mm_iptv_url); + tvherror("iptv", "unknown data %zd received for '%s'", len, im->mm_iptv_url_raw); return 0; } diff --git a/src/input/mpegts/mpegts_service.c b/src/input/mpegts/mpegts_service.c index 93d7c5bd8..c97a1702f 100644 --- a/src/input/mpegts/mpegts_service.c +++ b/src/input/mpegts/mpegts_service.c @@ -300,7 +300,7 @@ mpegts_service_enlist(service_t *t, tvh_input_t *ti, * Start service */ static int -mpegts_service_start(service_t *t, int instance, int flags) +mpegts_service_start(service_t *t, int instance, int weight, int flags) { int r; mpegts_service_t *s = (mpegts_service_t*)t; @@ -321,6 +321,7 @@ mpegts_service_start(service_t *t, int instance, int flags) return SM_CODE_UNDEFINED_ERROR; /* Start Mux */ + mmi->mmi_start_weight = weight; r = mpegts_mux_instance_start(&mmi, t); /* Start */ diff --git a/src/service.c b/src/service.c index 2a3ea0bdc..48a09360f 100644 --- a/src/service.c +++ b/src/service.c @@ -594,7 +594,8 @@ ignore: * */ int -service_start(service_t *t, int instance, int flags, int timeout, int postpone) +service_start(service_t *t, int instance, int weight, int flags, + int timeout, int postpone) { elementary_stream_t *st; int r, stimeout = 10; @@ -614,7 +615,7 @@ service_start(service_t *t, int instance, int flags, int timeout, int postpone) descrambler_caid_changed(t); pthread_mutex_unlock(&t->s_stream_mutex); - if((r = t->s_start_feed(t, instance, flags))) + if((r = t->s_start_feed(t, instance, weight, flags))) return r; descrambler_service_start(t); @@ -749,7 +750,7 @@ service_find_instance /* Start */ tvhtrace("service", "will start new instance %d", si->si_instance); - if (service_start(si->si_s, si->si_instance, flags, timeout, postpone)) { + if (service_start(si->si_s, si->si_instance, weight, flags, timeout, postpone)) { tvhtrace("service", "tuning failed"); si->si_error = SM_CODE_TUNING_FAILED; if (*error < SM_CODE_TUNING_FAILED) diff --git a/src/service.h b/src/service.h index 8a94ee09f..97dda55fe 100644 --- a/src/service.h +++ b/src/service.h @@ -296,7 +296,7 @@ typedef struct service { void (*s_enlist)(struct service *s, struct tvh_input *ti, service_instance_list_t *sil, int flags); - int (*s_start_feed)(struct service *s, int instance, int flags); + int (*s_start_feed)(struct service *s, int instance, int weight, int flags); void (*s_refresh_feed)(struct service *t); @@ -479,7 +479,8 @@ typedef struct service { void service_init(void); void service_done(void); -int service_start(service_t *t, int instance, int flags, int timeout, int postpone); +int service_start(service_t *t, int instance, int weight, int flags, + int timeout, int postpone); void service_stop(service_t *t); void service_build_filter(service_t *t); diff --git a/src/tvheadend.h b/src/tvheadend.h index fa7db598a..27402c9e1 100644 --- a/src/tvheadend.h +++ b/src/tvheadend.h @@ -727,7 +727,7 @@ char *regexp_escape ( const char *str ); /* URL decoding */ char to_hex(char code); -char *url_encode(char *str); +char *url_encode(const char *str); int mpegts_word_count(const uint8_t *tsb, int len, uint32_t mask); diff --git a/src/utils.c b/src/utils.c index 0390670aa..23ea46d6a 100644 --- a/src/utils.c +++ b/src/utils.c @@ -593,16 +593,17 @@ char to_hex(char code) { /* Returns a url-encoded version of str IMPORTANT: be sure to free() the returned string after use http://www.geekhideout.com/urlcode.shtml */ -char *url_encode(char *str) { - char *pstr = str, *buf = malloc(strlen(str) * 3 + 1), *pbuf = buf; - while (*pstr) { - if (isalnum(*pstr) || *pstr == '-' || *pstr == '_' || *pstr == '.' || *pstr == '~') - *pbuf++ = *pstr; - /*else if (*pstr == ' ') +char *url_encode(const char *str) +{ + char *buf = malloc(strlen(str) * 3 + 1), *pbuf = buf; + while (*str) { + if (isalnum(*str) || *str == '-' || *str == '_' || *str == '.' || *str == '~') + *pbuf++ = *str; + /*else if (*str == ' ') *pbuf++ = '+';*/ else - *pbuf++ = '%', *pbuf++ = to_hex(*pstr >> 4), *pbuf++ = to_hex(*pstr & 15); - pstr++; + *pbuf++ = '%', *pbuf++ = to_hex(*str >> 4), *pbuf++ = to_hex(*str & 15); + str++; } *pbuf = '\0'; return buf;