mpegts_mux_t *mmi_mux;
mpegts_input_t *mmi_input;
+ int mmi_start_weight;
int mmi_tune_failed;
};
#include "tvhpoll.h"
#include "tcp.h"
#include "settings.h"
+#include "htsstr.h"
#include <sys/socket.h>
#include <sys/types.h>
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;
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;
/* 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
pthread_mutex_unlock(&iptv_lock);
urlreset(&url);
+ free(s);
return ret;
}
.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",
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];
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);
mpegts_mux_delete(mm, delconf);
free(url);
free(url_sane);
+ free(url_raw);
free(muxname);
}
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;
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;
}
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;
}
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;
}
* 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;
return SM_CODE_UNDEFINED_ERROR;
/* Start Mux */
+ mmi->mmi_start_weight = weight;
r = mpegts_mux_instance_start(&mmi, t);
/* Start */
*
*/
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;
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);
/* 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)
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);
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);
/* 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);
/* 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;