Add support for content type for events.

This is (and will be) based on the content types described in EN 300 468

Still a lot to do
This commit is contained in:
Andreas Öman 2008-02-10 15:11:02 +00:00
parent 4487e78ee4
commit 2e0c9fa636
5 changed files with 85 additions and 7 deletions

View file

@ -36,6 +36,7 @@
#define DVB_DESC_SERVICE_LIST 0x41
#define DVB_DESC_SHORT_EVENT 0x4d
#define DVB_DESC_SERVICE 0x48
#define DVB_DESC_CONTENT 0x54
#define DVB_DESC_TELETEXT 0x56
#define DVB_DESC_SUBTITLE 0x59
#define DVB_DESC_AC3 0x6a

View file

@ -227,6 +227,7 @@ dvb_eit_callback(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len,
char title[256];
char desc[5000];
epg_content_type_t *ect;
if(tableid < 0x4e || tableid > 0x6f)
return -1;
@ -269,7 +270,10 @@ dvb_eit_callback(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len,
if(dllen > len)
break;
ect = NULL;
*title = 0;
*desc = 0;
while(dllen > 0) {
dtag = ptr[0];
dlen = ptr[1];
@ -286,6 +290,12 @@ dvb_eit_callback(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len,
desc, sizeof(desc)) < 0)
duration = 0;
break;
case DVB_DESC_CONTENT:
if(dlen >= 2)
/* We only support one content type per event atm. */
ect = epg_content_type_find_by_dvbcode(*ptr);
break;
}
len -= dlen; ptr += dlen; dllen -= dlen;
@ -293,7 +303,7 @@ dvb_eit_callback(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len,
if(duration > 0) {
epg_update_event_by_id(ch, event_id, start_time, duration,
title, desc);
title, desc, ect);
}
}

55
epg.c
View file

@ -36,6 +36,8 @@ static pthread_mutex_t epg_mutex = PTHREAD_MUTEX_INITIALIZER;
struct event_list epg_hash[EPG_HASH_ID_WIDTH];
static dtimer_t epg_channel_maintain_timer;
epg_content_group_t *epg_content_groups[16];
void
epg_lock(void)
{
@ -63,6 +65,16 @@ epg_event_set_desc(event_t *e, const char *desc)
e->e_desc = strdup(desc);
}
void
epg_event_set_content_type(event_t *e, epg_content_type_t *ect)
{
if(e->e_content_type != NULL)
LIST_REMOVE(e, e_content_type_link);
e->e_content_type = ect;
if(ect != NULL)
LIST_INSERT_HEAD(&ect->ect_events, e, e_content_type_link);
}
event_t *
epg_event_find_by_time0(struct event_queue *q, time_t start)
@ -157,6 +169,9 @@ epg_event_build(struct event_queue *head, time_t start, int duration)
void
epg_event_free(event_t *e)
{
if(e->e_content_type != NULL)
LIST_REMOVE(e, e_content_type_link);
free((void *)e->e_title);
free((void *)e->e_desc);
free(e);
@ -261,7 +276,7 @@ check_overlap(th_channel_t *ch, event_t *e)
static void
epg_event_create(th_channel_t *ch, time_t start, int duration,
const char *title, const char *desc, int source,
uint16_t id, refstr_t *icon)
uint16_t id, refstr_t *icon, epg_content_type_t *ect)
{
unsigned int l;
time_t now;
@ -317,6 +332,7 @@ epg_event_create(th_channel_t *ch, time_t start, int duration,
if(title != NULL) epg_event_set_title(e, title);
if(desc != NULL) epg_event_set_desc(e, desc);
if(ect != NULL) epg_event_set_content_type(e, ect);
}
check_overlap(ch, e);
@ -328,7 +344,7 @@ epg_event_create(th_channel_t *ch, time_t start, int duration,
void
epg_update_event_by_id(th_channel_t *ch, uint16_t event_id,
time_t start, int duration, const char *title,
const char *desc)
const char *desc, epg_content_type_t *ect)
{
event_t *e;
@ -359,11 +375,12 @@ epg_update_event_by_id(th_channel_t *ch, uint16_t event_id,
epg_event_set_title(e, title);
epg_event_set_desc(e, desc);
epg_event_set_content_type(e, ect);
} else {
epg_event_create(ch, start, duration, title, desc,
EVENT_SRC_DVB, event_id, NULL);
EVENT_SRC_DVB, event_id, NULL, ect);
}
}
@ -463,12 +480,42 @@ epg_transfer_events(th_channel_t *ch, struct event_queue *src,
TAILQ_FOREACH(e, src, e_link) {
epg_event_create(ch, e->e_start, e->e_duration, e->e_title,
e->e_desc, EVENT_SRC_XMLTV, 0, refstr_dup(icon));
e->e_desc, EVENT_SRC_XMLTV, 0, refstr_dup(icon),
e->e_content_type);
cnt++;
}
epg_unlock();
}
/**
* Find a content type
*/
epg_content_type_t *
epg_content_type_find_by_dvbcode(uint8_t dvbcode)
{
epg_content_group_t *ecg;
epg_content_type_t *ect;
int group = dvbcode >> 4;
int type = dvbcode & 0xf;
char buf[20];
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);
}
ect = ecg->ecg_types[type];
if(ect == NULL) {
ect = ecg->ecg_types[type] = calloc(1, sizeof(epg_content_type_t));
snprintf(buf, sizeof(buf), "type%d", type);
ect->ect_name = strdup(buf);
}
return ect;
}
/*

4
epg.h
View file

@ -43,7 +43,7 @@ void epg_event_set_desc(event_t *e, const char *desc);
void epg_update_event_by_id(th_channel_t *ch, uint16_t event_id,
time_t start, int duration, const char *title,
const char *desc);
const char *desc, epg_content_type_t *ect);
void epg_transfer_events(th_channel_t *ch, struct event_queue *src,
const char *srcname, refstr_t *icon);
@ -52,4 +52,6 @@ void event_time_txt(time_t start, int duration, char *out, int outlen);
event_t *epg_event_find_current_or_upcoming(th_channel_t *ch);
epg_content_type_t *epg_content_type_find_by_dvbcode(uint8_t dvbcode);
#endif /* EPG_H */

View file

@ -778,6 +778,21 @@ typedef struct th_subscription {
} th_subscription_t;
/**
* EPG content group
*
* Based on the content types defined in EN 300 468
*/
typedef struct epg_content_type {
const char *ect_name;
struct event_list ect_events;
} epg_content_type_t;
typedef struct epg_content_group {
const char *ecg_name;
struct epg_content_type *ecg_types[16];
} epg_content_group_t;
/*
@ -787,6 +802,9 @@ typedef struct event {
TAILQ_ENTRY(event) e_link;
LIST_ENTRY(event) e_hash_link;
LIST_ENTRY(event) e_content_type_link;
epg_content_type_t *e_content_type;
time_t e_start; /* UTC time */
int e_duration; /* in seconds */