From: Jaroslav Kysela Date: Wed, 14 Oct 2015 13:27:56 +0000 (+0200) Subject: IPTV: add icon per mux support (mainly for autonetworks) X-Git-Tag: v4.2.1~1918 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=0094a288afa46033c2afd922f3b06fb8f96e36d9;p=thirdparty%2Ftvheadend.git IPTV: add icon per mux support (mainly for autonetworks) --- diff --git a/src/channels.c b/src/channels.c index a161aff82..be5d984d6 100644 --- a/src/channels.c +++ b/src/channels.c @@ -604,12 +604,28 @@ channel_get_icon ( channel_t *ch ) const char *chicon = config.chicon_path, *picon = config.picon_path, *icon = ch->ch_icon, - *chname; + *chname, *icn; uint32_t id, i, pick, prefer = config.prefer_picon ? 1 : 0; if (icon && *icon == '\0') icon = NULL; + /* + * Initial lookup - for services with predefined icons (like M3U sources) + */ + if (icon == NULL) { + LIST_FOREACH(ilm, &ch->ch_services, ilm_in2_link) { + if (!(icn = service_get_channel_icon((service_t *)ilm->ilm_in1))) continue; + if (strncmp(icn, "picon://", 8) == 0) continue; + if (check_file(icn)) { + icon = ch->ch_icon = strdup(icn); + channel_save(ch); + idnode_notify_changed(&ch->ch_id); + goto found; + } + } + } + /* * 4 iterations: * 0,1: try channel name or picon @@ -679,7 +695,6 @@ channel_get_icon ( channel_t *ch ) /* No user icon - try access from services */ if (pick && picon) { LIST_FOREACH(ilm, &ch->ch_services, ilm_in2_link) { - const char *icn; if (!(icn = service_get_channel_icon((service_t *)ilm->ilm_in1))) continue; if (strncmp(icn, "picon://", 8)) continue; @@ -695,6 +710,8 @@ channel_get_icon ( channel_t *ch ) } +found: + /* Nothing */ if (!icon || !*icon) return NULL; diff --git a/src/input/mpegts/iptv/iptv.c b/src/input/mpegts/iptv/iptv.c index 695ae8fb6..d152c8f17 100644 --- a/src/input/mpegts/iptv/iptv.c +++ b/src/input/mpegts/iptv/iptv.c @@ -482,6 +482,8 @@ iptv_network_delete ( mpegts_network_t *mn, int delconf ) iptv_network_t *in = (iptv_network_t*)mn; char *url = in->in_url; char *sane_url = in->in_url_sane; + char *icon_url = in->in_icon_url; + char *icon_url_sane = in->in_icon_url_sane; if (in->mn_id.in_class == &iptv_auto_network_class) iptv_auto_network_done(in); @@ -495,6 +497,8 @@ iptv_network_delete ( mpegts_network_t *mn, int delconf ) free(in->in_remove_args); mpegts_network_delete(mn, delconf); + free(icon_url_sane); + free(icon_url); free(sane_url); free(url); } @@ -509,6 +513,13 @@ iptv_network_class_delete ( idnode_t *in ) return iptv_network_delete((mpegts_network_t *)in, 1); } +static int +iptv_network_class_icon_url_set( void *in, const void *v ) +{ + iptv_network_t *mn = in; + return iptv_url_set(&mn->in_icon_url, &mn->in_icon_url_sane, v, 1, 0); +} + extern const idclass_t mpegts_network_class; const idclass_t iptv_network_class = { .ic_super = &mpegts_network_class, @@ -553,6 +564,14 @@ const idclass_t iptv_network_class = { .off = offsetof(iptv_network_t, in_max_timeout), .def.i = 15, }, + { + .type = PT_STR, + .id = "icon_url", + .name = N_("Icon base URL"), + .off = offsetof(iptv_network_t, in_icon_url), + .set = iptv_network_class_icon_url_set, + .opts = PO_MULTILINE + }, {} } }; diff --git a/src/input/mpegts/iptv/iptv_auto.c b/src/input/mpegts/iptv/iptv_auto.c index 0263ab2c1..825de463e 100644 --- a/src/input/mpegts/iptv/iptv_auto.c +++ b/src/input/mpegts/iptv/iptv_auto.c @@ -25,6 +25,31 @@ #include #include +/* + * + */ +static char *get_m3u_str(char *data, char **res) +{ + char *p = data, first = *data; + + if (first == '"' || first == '\'') { + data++; + p = data; + while (*data && *data != first) + data++; + } else { + p = data; + while (*data && *data != ',' && *data > ' ') + data++; + } + *res = data; + if (*data) { + *data = '\0'; + (*res)++; + } + return p; +} + /* * */ @@ -33,6 +58,7 @@ iptv_auto_network_process_m3u_item(iptv_network_t *in, const char *last_url, const http_arg_list_t *remove_args, const char *url, const char *name, + const char *logo, int64_t chnum, int *total, int *count) { htsmsg_t *conf; @@ -122,11 +148,16 @@ iptv_auto_network_process_m3u_item(iptv_network_t *in, im->mm_iptv_chnum = chnum; change = 1; } - if ((1 || im->mm_iptv_muxname == NULL || im->mm_iptv_muxname[0] == '\0') && n && *n) { + if ((im->mm_iptv_muxname == NULL || im->mm_iptv_muxname[0] == '\0') && n && *n) { free(im->mm_iptv_muxname); im->mm_iptv_muxname = strdup(n); change = 1; } + if (strcmp(im->mm_iptv_icon ?: "", logo ?: "")) { + free(im->mm_iptv_icon); + im->mm_iptv_icon = logo ? strdup(logo) : NULL; + change = 1; + } if (change) idnode_notify_changed(&im->mm_id); (*total)++; @@ -161,7 +192,7 @@ iptv_auto_network_process_m3u(iptv_network_t *in, char *data, http_arg_list_t *remove_args, int64_t chnum) { - char *url, *name = NULL; + char *url, *name = NULL, *logo = NULL; int total = 0, count = 0; while (*data && *data != '\n') data++; @@ -169,8 +200,20 @@ iptv_auto_network_process_m3u(iptv_network_t *in, char *data, while (*data) { if (strncmp(data, "#EXTINF:", 8) == 0) { name = NULL; + logo = NULL; data += 8; - while (*data && *data != ',') data++; + while (1) { + while (*data && *data <= ' ') data++; + if (*data == ',') break; + if (strncmp(data, "tvg-logo=", 9) == 0) + logo = get_m3u_str(data + 9, &data); + else if (strncmp(data, "logo=", 5) == 0) + logo = get_m3u_str(data + 5, &data); + else { + data++; + while (*data && *data != ',' && *data > ' ') data++; + } + } if (*data == ',') { data++; while (*data && *data <= ' ') data++; @@ -186,7 +229,8 @@ iptv_auto_network_process_m3u(iptv_network_t *in, char *data, while (*data && *data != '\n') data++; if (*data) { *data = '\0'; data++; } if (*url) - iptv_auto_network_process_m3u_item(in, last_url, remove_args, url, name, + iptv_auto_network_process_m3u_item(in, last_url, remove_args, + url, name, logo, chnum, &total, &count); } diff --git a/src/input/mpegts/iptv/iptv_mux.c b/src/input/mpegts/iptv/iptv_mux.c index 8422e8a5b..691b251e2 100644 --- a/src/input/mpegts/iptv/iptv_mux.c +++ b/src/input/mpegts/iptv/iptv_mux.c @@ -169,6 +169,12 @@ const idclass_t iptv_mux_class = .name = N_("Channel number"), .off = offsetof(iptv_mux_t, mm_iptv_chnum), }, + { + .type = PT_STR, + .id = "iptv_icon", + .name = N_("Icon URL"), + .off = offsetof(iptv_mux_t, mm_iptv_icon), + }, { .type = PT_STR, .id = "iptv_sname", @@ -240,6 +246,7 @@ iptv_mux_delete ( mpegts_mux_t *mm, int delconf ) free(im->mm_iptv_interface); free(im->mm_iptv_svcname); free(im->mm_iptv_env); + free(im->mm_iptv_icon); mpegts_mux_delete(mm, delconf); free(url); free(url_sane); diff --git a/src/input/mpegts/iptv/iptv_private.h b/src/input/mpegts/iptv/iptv_private.h index f1632b331..3882eb2ae 100644 --- a/src/input/mpegts/iptv/iptv_private.h +++ b/src/input/mpegts/iptv/iptv_private.h @@ -85,6 +85,8 @@ struct iptv_network char *in_url_sane; int64_t in_channel_number; uint32_t in_refetch_period; + char *in_icon_url; + char *in_icon_url_sane; int in_ssl_peer_verify; char *in_remove_args; gtimer_t in_auto_timer; @@ -115,6 +117,7 @@ struct iptv_mux char *mm_iptv_muxname; char *mm_iptv_svcname; int64_t mm_iptv_chnum; + char *mm_iptv_icon; int mm_iptv_respawn; time_t mm_iptv_respawn_last; diff --git a/src/input/mpegts/iptv/iptv_service.c b/src/input/mpegts/iptv/iptv_service.c index 19e1d61e5..e19f813a0 100644 --- a/src/input/mpegts/iptv/iptv_service.c +++ b/src/input/mpegts/iptv/iptv_service.c @@ -77,6 +77,29 @@ iptv_service_channel_number ( service_t *s ) return mpegts_service_channel_number(s); } +static const char * +iptv_service_channel_icon ( service_t *s ) +{ + iptv_service_t *is = (iptv_service_t *)s; + iptv_mux_t *im = (iptv_mux_t *)is->s_dvb_mux; + iptv_network_t *in = (iptv_network_t *)im->mm_network; + const char *ic = im->mm_iptv_icon; + if (ic && ic[0]) { + if (strncmp(ic, "http://", 7) == 0 || + strncmp(ic, "https://", 8) == 0) + return ic; + if (strncmp(ic, "file:///", 8) == 0) + return ic + 7; + if (strncmp(ic, "file://", 7) == 0) + ic += 7; + if (in && in->in_icon_url && in->in_icon_url[0]) { + snprintf(prop_sbuf, PROP_SBUF_LEN, "%s/%s", in->in_icon_url, ic + 7); + return prop_sbuf; + } + } + return NULL; +} + /* * Create */ @@ -94,6 +117,7 @@ iptv_service_create0 is->s_delete = iptv_service_delete; is->s_channel_name = iptv_service_channel_name; is->s_channel_number = iptv_service_channel_number; + is->s_channel_icon = iptv_service_channel_icon; /* Set default service name */ if (!is->s_dvb_svcname || !*is->s_dvb_svcname) diff --git a/src/input/mpegts/mpegts_service.c b/src/input/mpegts/mpegts_service.c index bd145dc53..d118037ad 100644 --- a/src/input/mpegts/mpegts_service.c +++ b/src/input/mpegts/mpegts_service.c @@ -497,7 +497,6 @@ mpegts_service_channel_icon ( service_t *s ) if (ms->s_dvb_mux && idnode_is_instance(&ms->s_dvb_mux->mm_id, &dvb_mux_class)) { int32_t hash = 0; - static char buf[128]; dvb_mux_t *mmd = (dvb_mux_t*)ms->s_dvb_mux; int pos; @@ -525,14 +524,14 @@ mpegts_service_channel_icon ( service_t *s ) return NULL; } - snprintf(buf, sizeof(buf), + snprintf(prop_sbuf, PROP_SBUF_LEN, "picon://1_0_%X_%X_%X_%X_%X_0_0_0.png", ms->s_dvb_servicetype, ms->s_dvb_service_id, ms->s_dvb_mux->mm_tsid, ms->s_dvb_mux->mm_onid, hash); - return buf; + return prop_sbuf; } #endif