From 2e0c9fa63670718a71c7274c5f29c2ec709200ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=96man?= Date: Sun, 10 Feb 2008 15:11:02 +0000 Subject: [PATCH] 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 --- dvb_support.h | 1 + dvb_tables.c | 14 +++++++++++-- epg.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++---- epg.h | 4 +++- tvhead.h | 18 +++++++++++++++++ 5 files changed, 85 insertions(+), 7 deletions(-) diff --git a/dvb_support.h b/dvb_support.h index 49cc4805..2cef686b 100644 --- a/dvb_support.h +++ b/dvb_support.h @@ -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 diff --git a/dvb_tables.c b/dvb_tables.c index 3b149e44..b64228d4 100644 --- a/dvb_tables.c +++ b/dvb_tables.c @@ -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); } } diff --git a/epg.c b/epg.c index d9956fc5..d7fdb205 100644 --- a/epg.c +++ b/epg.c @@ -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; +} + /* diff --git a/epg.h b/epg.h index a1802059..48a2660d 100644 --- a/epg.h +++ b/epg.h @@ -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 */ diff --git a/tvhead.h b/tvhead.h index b7811a42..d4975024 100644 --- a/tvhead.h +++ b/tvhead.h @@ -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 */