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
/* 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;
}
+found:
+
/* Nothing */
if (!icon || !*icon)
return NULL;
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);
free(in->in_remove_args);
mpegts_network_delete(mn, delconf);
+ free(icon_url_sane);
+ free(icon_url);
free(sane_url);
free(url);
}
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,
.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
+ },
{}
}
};
#include <fcntl.h>
#include <sys/stat.h>
+/*
+ *
+ */
+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;
+}
+
/*
*
*/
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;
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)++;
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++;
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++;
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);
}
.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",
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);
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;
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;
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
*/
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)
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;
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