Add content based TV guide in HTML interface

This commit is contained in:
Andreas Öman 2008-02-10 20:01:29 +00:00
parent 2e0c9fa636
commit b58371f4e8
4 changed files with 165 additions and 18 deletions

17
epg.c
View file

@ -487,6 +487,20 @@ epg_transfer_events(th_channel_t *ch, struct event_queue *src,
epg_unlock();
}
static const char *groupnames[16] = {
[1] = "Movie / Drama",
[2] = "News / Current affairs",
[3] = "Show / Games",
[4] = "Sports",
[5] = "Children's/Youth",
[6] = "Music",
[7] = "Art/Culture",
[8] = "Social/Political issues/Economics",
[9] = "Education/Science/Factual topics",
[10] = "Leisure hobbies",
[11] = "Special characteristics",
};
/**
* Find a content type
*/
@ -502,8 +516,7 @@ epg_content_type_find_by_dvbcode(uint8_t dvbcode)
ecg = epg_content_groups[group];
if(ecg == NULL) {
ecg = epg_content_groups[group] = calloc(1, sizeof(epg_content_group_t));
snprintf(buf, sizeof(buf), "group%d", group);
ecg->ecg_name = strdup(buf);
ecg->ecg_name = groupnames[group] ?: "Unknown";
}
ect = ecg->ecg_types[type];

2
epg.h
View file

@ -19,6 +19,8 @@
#ifndef EPG_H
#define EPG_H
extern epg_content_group_t *epg_content_groups[16];
void epg_init(void);
void epg_lock(void);

163
htmlui.c
View file

@ -40,6 +40,8 @@
#include "iptv_input.h"
#include "transports.h"
#define MAIN_WIDTH 800
static struct strtab recstatustxt[] = {
{ "Recording scheduled",HTSTV_PVR_STATUS_SCHEDULED },
{ "Recording", HTSTV_PVR_STATUS_RECORDING },
@ -265,7 +267,7 @@ box_bottom(tcp_queue_t *tq)
static void
top_menu(http_connection_t *hc, tcp_queue_t *tq)
{
tcp_qprintf(tq, "<div style=\"width: 700px; "
tcp_qprintf(tq, "<div style=\"width: 800px; "
"margin-left: auto; margin-right: auto\">");
box_top(tq, "box");
@ -275,7 +277,9 @@ top_menu(http_connection_t *hc, tcp_queue_t *tq)
"<ul id=\"meny\">");
tcp_qprintf(tq, "<li><a href=\"/\">TV Guide</a></li>");
tcp_qprintf(tq, "<li><a href=\"/\">Channel Guide</a></li>");
tcp_qprintf(tq, "<li><a href=\"/contentlist\">Content Guide</a></li>");
if(html_verify_access(hc, "record-events"))
tcp_qprintf(tq, "<li><a href=\"/pvrlog\">Recordings</a></li>");
@ -345,7 +349,7 @@ is_client_simple(http_connection_t *hc)
static void
output_event(http_connection_t *hc, tcp_queue_t *tq, th_channel_t *ch,
event_t *e, int simple)
event_t *e, int simple, int print_channel)
{
char title[100];
char bufa[4000];
@ -383,17 +387,24 @@ output_event(http_connection_t *hc, tcp_queue_t *tq, th_channel_t *ch,
"javascript:epop('/event/%d')", e->e_tag);
}
esacpe_char(title, sizeof(title), e->e_title, '"', "'");
tcp_qprintf(tq, "<div><a href=\"%s\" %s>", bufa, overlibstuff);
if(print_channel) {
esacpe_char(title, sizeof(title), ch->ch_name, '"', "'");
tcp_qprintf(tq,
"<span style=\"width: %dpx;float: left\">"
"%s</span>",
simple ? 80 : 150, title);
}
esacpe_char(title, sizeof(title), e->e_title, '"', "'");
tcp_qprintf(tq,
"<div>"
"<a href=\"%s\" %s>"
"<span style=\"width: %dpx;float: left%s\">"
"%02d:%02d - %02d:%02d</span>"
"<span style=\"overflow: hidden; height: 15px; width: %dpx; "
"float: left%s\">%s</span>",
bufa,
overlibstuff,
simple ? 80 : 100,
e == cur ? ";font-weight:bold" : "",
a.tm_hour, a.tm_min, b.tm_hour, b.tm_min,
@ -446,7 +457,7 @@ page_root(http_connection_t *hc, const char *remain, void *opaque)
if(i < 30)
i = 30;
html_header(&tq, "HTS/tvheadend", !simple, 700, i);
html_header(&tq, "HTS/tvheadend", !simple, MAIN_WIDTH, i);
top_menu(hc, &tq);
TAILQ_FOREACH(tcg, &all_channel_groups, tcg_global_link) {
@ -498,7 +509,7 @@ page_root(http_connection_t *hc, const char *remain, void *opaque)
for(i = 0; i < 3 && e != NULL; i++) {
output_event(hc, &tq, ch, e, simple);
output_event(hc, &tq, ch, e, simple, 0);
e = TAILQ_NEXT(e, e_link);
}
@ -559,7 +570,7 @@ page_channel(http_connection_t *hc, const char *remain, void *opaque)
tcp_init_queue(&tq, -1);
html_header(&tq, "HTS/tvheadend", !simple, 700, 0);
html_header(&tq, "HTS/tvheadend", !simple, MAIN_WIDTH, 0);
top_menu(hc, &tq);
@ -591,7 +602,7 @@ page_channel(http_connection_t *hc, const char *remain, void *opaque)
break;
if(a.tm_wday == wday + doff) {
output_event(hc, &tq, ch, e, simple);
output_event(hc, &tq, ch, e, simple, 0);
}
e = TAILQ_NEXT(e, e_link);
}
@ -676,7 +687,7 @@ page_event(http_connection_t *hc, const char *remain, void *opaque)
tcp_init_queue(&tq, -1);
html_header(&tq, "HTS/tvheadend", 0, 700, 0);
html_header(&tq, "HTS/tvheadend", 0, MAIN_WIDTH, 0);
top_menu(hc, &tq);
tcp_qprintf(&tq, "<form method=\"get\" action=\"/event/%d\">", eventid);
@ -782,7 +793,7 @@ page_pvrlog(http_connection_t *hc, const char *remain, void *opaque)
return HTTP_STATUS_UNAUTHORIZED;
tcp_init_queue(&tq, -1);
html_header(&tq, "HTS/tvheadend", 0, 700, 0);
html_header(&tq, "HTS/tvheadend", 0, MAIN_WIDTH, 0);
top_menu(hc, &tq);
box_top(&tq, "box");
@ -889,6 +900,124 @@ page_pvrlog(http_connection_t *hc, const char *remain, void *opaque)
return 0;
}
/**
* Content listing
*/
static int
eventcmp(const void *A, const void *B)
{
const event_t *a = *(const event_t **)A;
const event_t *b = *(const event_t **)B;
return a->e_start - b->e_start;
}
static int
page_contentlist(http_connection_t *hc, const char *remain, void *opaque)
{
tcp_queue_t tq;
int simple = is_client_simple(hc);
event_t *e, **ev;
int c, i, j, k;
struct tm a, day;
th_channel_t *ch;
epg_content_group_t *ecg;
epg_content_type_t *ect;
th_channel_group_t *dis;
struct event_list events;
dis = channel_group_find("-disabled-", 1);
tcp_init_queue(&tq, -1);
html_header(&tq, "HTS/tvheadend", !simple, MAIN_WIDTH, 0);
top_menu(hc, &tq);
epg_lock();
for(i = 1; i < 17; i++) {
if((ecg = epg_content_groups[i & 0xf]) == NULL)
continue;
LIST_INIT(&events);
c = 0;
for(j = 0; j < 16; j++) {
if((ect = ecg->ecg_types[j]) == NULL)
continue;
LIST_FOREACH(e, &ect->ect_events, e_content_type_link) {
ch = e->e_ch;
if(ch->ch_group == dis)
continue;
if(e->e_start + e->e_duration < dispatch_clock)
continue;
LIST_INSERT_HEAD(&events, e, e_tmp_link);
c++;
}
}
if(c == 0)
continue;
ev = alloca(c * sizeof(event_t *));
c = 0;
LIST_FOREACH(e, &events, e_tmp_link)
ev[c++] = e;
qsort(ev, c, sizeof(event_t *), eventcmp);
box_top(&tq, "box");
tcp_qprintf(&tq,
"<div class=\"contentbig\">"
"<center><b>%s</b></center></div>", ecg->ecg_name);
tcp_qprintf(&tq, "<div class=\"content\">");
if(c > 25)
c = 25;
memset(&day, -1, sizeof(struct tm));
for(k = 0; k < c; k++) {
e = ev[k];
localtime_r(&e->e_start, &a);
if(a.tm_wday != day.tm_wday ||
a.tm_mday != day.tm_mday ||
a.tm_mon != day.tm_mon ||
a.tm_year != day.tm_year) {
memcpy(&day, &a, sizeof(struct tm));
tcp_qprintf(&tq,
"<br><b><i>%s, %d/%d</i></b><br>",
days[day.tm_wday],
day.tm_mday,
day.tm_mon + 1);
}
output_event(hc, &tq, e->e_ch, e, simple, 1);
}
tcp_qprintf(&tq, "</div>");
box_bottom(&tq);
tcp_qprintf(&tq, "<br>\r\n");
}
epg_unlock();
tcp_qprintf(&tq, "<br></div>\r\n");
html_footer(&tq);
http_output_queue(hc, &tq, "text/html; charset=UTF-8", 0);
return 0;
}
static void
html_iptv_status(tcp_queue_t *tq, th_transport_t *t, const char *status)
@ -1276,7 +1405,7 @@ page_chgroups(http_connection_t *hc, const char *remain, void *opaque)
tcp_init_queue(&tq, -1);
html_header(&tq, "HTS/tvheadend", 0, 700, 0);
html_header(&tq, "HTS/tvheadend", 0, MAIN_WIDTH, 0);
top_menu(hc, &tq);
@ -1346,7 +1475,7 @@ page_chadm(http_connection_t *hc, const char *remain, void *opaque)
return HTTP_STATUS_UNAUTHORIZED;
tcp_init_queue(&tq, -1);
html_header(&tq, "HTS/tvheadend", !simple, 800, 0);
html_header(&tq, "HTS/tvheadend", !simple, MAIN_WIDTH, 0);
top_menu(hc, &tq);
tcp_qprintf(&tq,
@ -1629,4 +1758,6 @@ htmlui_start(void)
http_path_add("/editchannel", NULL, page_editchannel);
http_path_add("/updatechannel", NULL, page_updatechannel);
http_path_add("/css.css", NULL, page_css);
http_path_add("/contentlist", NULL, page_contentlist);
}

View file

@ -801,6 +801,7 @@ typedef struct epg_content_group {
typedef struct event {
TAILQ_ENTRY(event) e_link;
LIST_ENTRY(event) e_hash_link;
LIST_ENTRY(event) e_tmp_link;
LIST_ENTRY(event) e_content_type_link;
epg_content_type_t *e_content_type;