Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
IPTV: Add $m $n $w formatters (mux name, service name, start subscrip…
…tion weight), fixes #2608
  • Loading branch information
perexg committed Oct 6, 2015
1 parent 75f4f0d commit f0c315c
Show file tree
Hide file tree
Showing 11 changed files with 94 additions and 25 deletions.
1 change: 1 addition & 0 deletions src/input/mpegts.h
Expand Up @@ -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;
};

Expand Down
64 changes: 59 additions & 5 deletions src/input/mpegts/iptv/iptv.c
Expand Up @@ -21,6 +21,7 @@
#include "tvhpoll.h"
#include "tcp.h"
#include "settings.h"
#include "htsstr.h"

#include <sys/socket.h>
#include <sys/types.h>
Expand Down Expand Up @@ -198,32 +199,82 @@ 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;

/* Already active */
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;
Expand All @@ -239,16 +290,19 @@ 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
im->mm_active = NULL;
pthread_mutex_unlock(&iptv_lock);

urlreset(&url);
free(s);
return ret;
}

Expand Down
10 changes: 9 additions & 1 deletion src/input/mpegts/iptv/iptv_mux.c
Expand Up @@ -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",
Expand Down Expand Up @@ -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];

Expand All @@ -213,13 +219,15 @@ 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);
free(im->mm_iptv_env);
mpegts_mux_delete(mm, delconf);
free(url);
free(url_sane);
free(url_raw);
free(muxname);
}

Expand Down
4 changes: 2 additions & 2 deletions src/input/mpegts/iptv/iptv_pipe.c
Expand Up @@ -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;
Expand Down
2 changes: 2 additions & 0 deletions src/input/mpegts/iptv/iptv_private.h
Expand Up @@ -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;
Expand Down
4 changes: 2 additions & 2 deletions src/input/mpegts/iptv/iptv_rtsp.c
Expand Up @@ -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;
}

Expand Down Expand Up @@ -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;
}
Expand Down
3 changes: 2 additions & 1 deletion src/input/mpegts/mpegts_service.c
Expand Up @@ -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;
Expand All @@ -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 */
Expand Down
7 changes: 4 additions & 3 deletions src/service.c
Expand Up @@ -594,7 +594,8 @@ service_build_filter(service_t *t)
*
*/
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;
Expand All @@ -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);
Expand Down Expand Up @@ -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)
Expand Down
5 changes: 3 additions & 2 deletions src/service.h
Expand Up @@ -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);

Expand Down Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion src/tvheadend.h
Expand Up @@ -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);

Expand Down
17 changes: 9 additions & 8 deletions src/utils.c
Expand Up @@ -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;
Expand Down

0 comments on commit f0c315c

Please sign in to comment.