From: Jaroslav Kysela Date: Wed, 14 Feb 2018 12:14:22 +0000 (+0100) Subject: epg: remove episode object X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ae2c76c7886dbec3c2d420b734659ce97a62fc72;p=thirdparty%2Ftvheadend.git epg: remove episode object --- diff --git a/src/api/api_epg.c b/src/api/api_epg.c index daf66e3dc..2fba65cd5 100644 --- a/src/api/api_epg.c +++ b/src/api/api_epg.c @@ -76,7 +76,6 @@ api_epg_entry ( epg_broadcast_t *eb, const char *lang, access_t *perm, const cha { const char *s; char buf[64]; - epg_episode_t *ee = eb->episode; channel_t *ch = eb->channel; htsmsg_t *m, *m2; epg_episode_num_t epnum; @@ -84,7 +83,7 @@ api_epg_entry ( epg_broadcast_t *eb, const char *lang, access_t *perm, const cha dvr_entry_t *de; char ubuf[UUID_HEX_SIZE]; - if (!ee || !ch) return NULL; + if (!ch) return NULL; if (*blank == NULL) *blank = tvh_gettext_lang(lang, channel_blank_name); @@ -93,11 +92,8 @@ api_epg_entry ( epg_broadcast_t *eb, const char *lang, access_t *perm, const cha /* EPG IDs */ htsmsg_add_u32(m, "eventId", eb->id); - if (ee) { - htsmsg_add_u32(m, "episodeId", ee->id); - if (ee->uri && strncasecmp(ee->uri, "tvh://", 6)) - htsmsg_add_str(m, "episodeUri", ee->uri); - } + if (eb->episode_uri && strncasecmp(eb->episode_uri, "tvh://", 6)) + htsmsg_add_str(m, "episodeUri", eb->episode_uri); if (eb->serieslink_uri) htsmsg_add_str(m, "serieslinkUri", eb->serieslink_uri); @@ -141,62 +137,60 @@ api_epg_entry ( epg_broadcast_t *eb, const char *lang, access_t *perm, const cha htsmsg_add_u32(m, "audiodesc", eb->is_audio_desc); if (eb->is_hd) htsmsg_add_u32(m, "hd", eb->is_hd); + if (eb->is_bw) + htsmsg_add_u32(m, "bw", eb->is_bw); if (eb->lines) htsmsg_add_u32(m, "lines", eb->lines); if (eb->aspect) htsmsg_add_u32(m, "aspect", eb->aspect); /* Episode info */ - if (ee) { - - /* Number */ - epg_episode_get_epnum(ee, &epnum); - if (epnum.s_num) { - htsmsg_add_u32(m, "seasonNumber", epnum.s_num); - if (epnum.s_cnt) - htsmsg_add_u32(m, "seasonCount", epnum.s_cnt); - } - if (epnum.e_num) { - htsmsg_add_u32(m, "episodeNumber", epnum.e_num); - if (epnum.e_cnt) - htsmsg_add_u32(m, "episodeCount", epnum.e_cnt); - } - if (epnum.p_num) { - htsmsg_add_u32(m, "partNumber", epnum.p_num); - if (epnum.p_cnt) - htsmsg_add_u32(m, "partCount", epnum.p_cnt); - } - if (epnum.text) - htsmsg_add_str(m, "episodeOnscreen", epnum.text); - else if (epg_episode_number_format(ee, buf, sizeof(buf), NULL, - "s%02d", ".", "e%02d", "")) - htsmsg_add_str(m, "episodeOnscreen", buf); - - /* Image */ - if (ee->image) - htsmsg_add_str(m, "image", ee->image); - - /* Rating */ - if (ee->star_rating) - htsmsg_add_u32(m, "starRating", ee->star_rating); - if (ee->age_rating) - htsmsg_add_u32(m, "ageRating", ee->age_rating); - - if (ee->first_aired) - htsmsg_add_s64(m, "first_aired", ee->first_aired); - if (ee->copyright_year) - htsmsg_add_u32(m, "copyright_year", ee->copyright_year); - - /* Content Type */ - m2 = NULL; - LIST_FOREACH(eg, &ee->genre, link) { - if (m2 == NULL) - m2 = htsmsg_create_list(); - htsmsg_add_u32(m2, NULL, eg->code); - } - if (m2) - htsmsg_add_msg(m, "genre", m2); + epg_broadcast_get_epnum(eb, &epnum); + if (epnum.s_num) { + htsmsg_add_u32(m, "seasonNumber", epnum.s_num); + if (epnum.s_cnt) + htsmsg_add_u32(m, "seasonCount", epnum.s_cnt); + } + if (epnum.e_num) { + htsmsg_add_u32(m, "episodeNumber", epnum.e_num); + if (epnum.e_cnt) + htsmsg_add_u32(m, "episodeCount", epnum.e_cnt); } + if (epnum.p_num) { + htsmsg_add_u32(m, "partNumber", epnum.p_num); + if (epnum.p_cnt) + htsmsg_add_u32(m, "partCount", epnum.p_cnt); + } + if (epnum.text) + htsmsg_add_str(m, "episodeOnscreen", epnum.text); + else if (epg_broadcast_epnumber_format(eb, buf, sizeof(buf), NULL, + "s%02d", ".", "e%02d", "")) + htsmsg_add_str(m, "episodeOnscreen", buf); + + /* Image */ + if (eb->image) + htsmsg_add_str(m, "image", eb->image); + + /* Rating */ + if (eb->star_rating) + htsmsg_add_u32(m, "starRating", eb->star_rating); + if (eb->age_rating) + htsmsg_add_u32(m, "ageRating", eb->age_rating); + + if (eb->first_aired) + htsmsg_add_s64(m, "first_aired", eb->first_aired); + if (eb->copyright_year) + htsmsg_add_u32(m, "copyright_year", eb->copyright_year); + + /* Content Type */ + m2 = NULL; + LIST_FOREACH(eg, &eb->genre, link) { + if (m2 == NULL) + m2 = htsmsg_create_list(); + htsmsg_add_u32(m2, NULL, eg->code); + } + if (m2) + htsmsg_add_msg(m, "genre", m2); /* Recording */ if (eb->channel && !access_verify2(perm, ACCESS_RECORDER)) { @@ -514,21 +508,26 @@ api_epg_grid static void api_epg_episode_broadcasts - ( access_t *perm, htsmsg_t *l, const char *lang, epg_episode_t *ep, + ( access_t *perm, htsmsg_t *l, const char *lang, epg_broadcast_t *ep, uint32_t *entries, epg_broadcast_t *ebc_skip ) { epg_broadcast_t *ebc; channel_t *ch; htsmsg_t *m; + const char *uri = ep->episode_uri; - LIST_FOREACH(ebc, &ep->broadcasts, ep_link) { - ch = ebc->channel; - if (ch == NULL) continue; - if (ebc == ebc_skip) continue; - m = api_epg_entry(ebc, lang, perm, NULL); - htsmsg_add_msg(l, NULL, m); - (*entries)++; - } + if (uri == NULL || uri[0] == '\0') + return; + + CHANNEL_FOREACH(ch) + if (channel_access(ch, perm, 0)) + RB_FOREACH(ebc, &ch->ch_epg_schedule, sched_link) + if (ebc && ebc->episode_uri && ebc != ebc_skip && + strcmp(uri, ebc->episode_uri) == 0) { + m = api_epg_entry(ebc, lang, perm, NULL); + htsmsg_add_msg(l, NULL, m); + (*entries)++; + } } static int @@ -547,8 +546,8 @@ api_epg_alternative lang = access_get_lang(perm, htsmsg_get_str(args, "lang")); pthread_mutex_lock(&global_lock); e = epg_broadcast_find_by_id(id); - if (e && e->episode) - api_epg_episode_broadcasts(perm, l, lang, e->episode, &entries, e); + if (e) + api_epg_episode_broadcasts(perm, l, lang, e, &entries, e); pthread_mutex_unlock(&global_lock); free(lang); diff --git a/src/dvr/dvr_autorec.c b/src/dvr/dvr_autorec.c index d3c607ed0..e140d72a9 100644 --- a/src/dvr/dvr_autorec.c +++ b/src/dvr/dvr_autorec.c @@ -151,7 +151,6 @@ autorec_cmp(dvr_autorec_entry_t *dae, epg_broadcast_t *e) double duration; if (!e->channel) return 0; - if (!e->episode) return 0; if(dae->dae_enabled == 0 || dae->dae_weekdays == 0) return 0; @@ -205,7 +204,7 @@ autorec_cmp(dvr_autorec_entry_t *dae, epg_broadcast_t *e) epg_genre_t ct; memset(&ct, 0, sizeof(ct)); ct.code = dae->dae_content_type; - if (!epg_genre_list_contains(&e->episode->genre, &ct, 1)) + if (!epg_genre_list_contains(&e->genre, &ct, 1)) return 0; } @@ -274,8 +273,8 @@ autorec_cmp(dvr_autorec_entry_t *dae, epg_broadcast_t *e) * dae_star_rating is zero then that means "do not check * star rating of episode". */ - if (e->episode && dae->dae_star_rating) - if (e->episode->star_rating < dae->dae_star_rating) + if (dae->dae_star_rating) + if (e->star_rating < dae->dae_star_rating) return 0; /* Do not check title if the event is from the serieslink group */ @@ -283,16 +282,16 @@ autorec_cmp(dvr_autorec_entry_t *dae, epg_broadcast_t *e) dae->dae_title != NULL && dae->dae_title[0] != '\0') { lang_str_ele_t *ls; if (!dae->dae_fulltext) { - if(!e->episode->title) return 0; - RB_FOREACH(ls, e->episode->title, link) + if(!e->title) return 0; + RB_FOREACH(ls, e->title, link) if (!regex_match(&dae->dae_title_regex, ls->str)) break; } else { ls = NULL; - if (e->episode->title) - RB_FOREACH(ls, e->episode->title, link) + if (e->title) + RB_FOREACH(ls, e->title, link) if (!regex_match(&dae->dae_title_regex, ls->str)) break; - if (!ls && e->episode->subtitle) - RB_FOREACH(ls, e->episode->subtitle, link) + if (!ls && e->subtitle) + RB_FOREACH(ls, e->subtitle, link) if (!regex_match(&dae->dae_title_regex, ls->str)) break; if (!ls && e->summary) RB_FOREACH(ls, e->summary, link) @@ -388,7 +387,7 @@ dvr_autorec_add_series_link(const char *dvr_config_name, const char *chname; char *title; const char *name; - if (!event || !event->episode) + if (!event) return NULL; chname = channel_get_name(event->channel, NULL); if (!chname) diff --git a/src/dvr/dvr_db.c b/src/dvr/dvr_db.c index 28560be07..6fdf9d441 100644 --- a/src/dvr/dvr_db.c +++ b/src/dvr/dvr_db.c @@ -826,11 +826,11 @@ recording: static char * dvr_entry_get_episode(epg_broadcast_t *bcast, char *buf, int len) { - if (!bcast || !bcast->episode) + if (!bcast) return NULL; - if (epg_episode_number_format(bcast->episode, - buf, len, NULL, - _("Season %d"), ".", _("Episode %d"), "/%d")) + if (epg_broadcast_epnumber_format(bcast, + buf, len, NULL, + _("Season %d"), ".", _("Episode %d"), "/%d")) return buf; return NULL; } @@ -870,7 +870,7 @@ dvr_entry_fuzzy_match(dvr_entry_t *de, epg_broadcast_t *e, uint16_t eid, int64_t return 0; /* episode check */ - epg_episode_get_epnum(e->episode, &epnum); + epg_broadcast_get_epnum(e, &epnum); if (epg_episode_number_cmpfull(&epnum, &de->de_epnum)) return 0; @@ -1043,32 +1043,27 @@ dvr_entry_create_from_htsmsg(htsmsg_t *conf, epg_broadcast_t *e) htsmsg_add_s64(conf, "start", e->start); if (!htsmsg_field_find(conf, "stop")) htsmsg_add_s64(conf, "stop", e->stop); - if (e->episode && e->episode->title) - lang_str_serialize(e->episode->title, conf, "title"); - if (e->episode && e->episode->subtitle) - lang_str_serialize(e->episode->subtitle, conf, "subtitle"); + if (e->title) + lang_str_serialize(e->title, conf, "title"); + if (e->subtitle) + lang_str_serialize(e->subtitle, conf, "subtitle"); if (e->description) lang_str_serialize(e->description, conf, "description"); - else if (e->episode && e->episode->description) - lang_str_serialize(e->episode->description, conf, "description"); else if (e->summary) { lang_str_serialize(e->summary, conf, "description"); summary_used = 1; - } else if (e->episode && e->episode->summary) - lang_str_serialize(e->episode->summary, conf, "description"); + } if (!summary_used && e->summary) lang_str_serialize(e->summary, conf, "summary"); - else if (e->episode && e->episode->summary) - lang_str_serialize(e->episode->summary, conf, "summary"); - if (e->episode && (s = dvr_entry_get_episode(e, tbuf, sizeof(tbuf)))) + if ((s = dvr_entry_get_episode(e, tbuf, sizeof(tbuf))) != NULL) htsmsg_add_str(conf, "episode", s); - if (e->episode && e->episode->copyright_year) - htsmsg_add_u32(conf, "copyright_year", e->episode->copyright_year); - if (e->episode && e->episode->uri) - htsmsg_add_str(conf, "uri", e->episode->uri); - if (e->episode && e->episode->image) - htsmsg_add_str(conf, "image", e->episode->image); - genre = LIST_FIRST(&e->episode->genre); + if (e->copyright_year) + htsmsg_add_u32(conf, "copyright_year", e->copyright_year); + if (e->episode_uri) + htsmsg_add_str(conf, "uri", e->episode_uri); + if (e->image) + htsmsg_add_str(conf, "image", e->image); + genre = LIST_FIRST(&e->genre); if (genre) htsmsg_add_u32(conf, "content_type", genre->code / 16); } @@ -1124,7 +1119,7 @@ static time_t dvr_entry_get_segment_stop_extra( dvr_entry_t *de ) return 0; } - ep_uri = e->episode->uri; + ep_uri = e->episode_uri; /* If not a segmented programme then no segment extra time */ if (!ep_uri || strncmp(ep_uri, "crid://", 7) || !strstr(ep_uri, "#")) @@ -1160,9 +1155,9 @@ static time_t dvr_entry_get_segment_stop_extra( dvr_entry_t *de ) max_progs_to_check = 10; for (next = epg_broadcast_get_next(e); --max_progs_to_check && stop < maximum_stop_time && - next && next->episode && next->start < stop + THREE_HOURS; + next && next->start < stop + THREE_HOURS; next = epg_broadcast_get_next(next)) { - next_uri = next->episode->uri; + next_uri = next->episode_uri; if (next_uri && strcmp(ep_uri, next_uri) == 0) { /* Identical CRID+IMI. So that means that programme is a * segment part of this programme. So extend our stop time @@ -1170,7 +1165,7 @@ static time_t dvr_entry_get_segment_stop_extra( dvr_entry_t *de ) */ segment_stop_extra = next->stop - stop; tvhinfo(LS_DVR, "Increasing stop for \"%s\" on \"%s\" \"%s\" by %"PRId64" seconds at start %"PRId64" and original stop %"PRId64, - lang_str_get(e->episode->title, NULL), DVR_CH_NAME(de), ep_uri, (int64_t)segment_stop_extra, (int64_t)start, (int64_t)stop); + lang_str_get(e->title, NULL), DVR_CH_NAME(de), ep_uri, (int64_t)segment_stop_extra, (int64_t)start, (int64_t)stop); } } @@ -1690,7 +1685,7 @@ dvr_entry_create_by_autorec(int enabled, epg_broadcast_t *e, dvr_autorec_entry_t /* Identical duplicate detection NOTE: Semantic duplicate detection is deferred to the start time of recording and then done using _dvr_duplicate_event by dvr_timer_start_recording. */ LIST_FOREACH(de, &dvrentries, de_global_link) { - if (de->de_bcast == e || (de->de_bcast && de->de_bcast->episode == e->episode)) + if (de->de_bcast == e || epg_episode_match(de->de_bcast, e)) if (strcmp(dae->dae_owner ?: "", de->de_owner ?: "") == 0) return; } @@ -1704,7 +1699,7 @@ dvr_entry_create_by_autorec(int enabled, epg_broadcast_t *e, dvr_autorec_entry_t if (count >= max_count) { tvhinfo(LS_DVR, "Autorecord \"%s\": Not scheduling \"%s\" because of autorecord max schedules limit reached", - dae->dae_name, lang_str_get(e->episode->title, NULL)); + dae->dae_name, lang_str_get(e->title, NULL)); return; } } @@ -2066,22 +2061,22 @@ static dvr_entry_t *_dvr_entry_update } /* Title */ - if (e && e->episode && e->episode->title) { - save |= lang_str_set2(&de->de_title, e->episode->title) ? DVR_UPDATED_TITLE : 0; + if (e && e->title) { + save |= lang_str_set2(&de->de_title, e->title) ? DVR_UPDATED_TITLE : 0; } else if (title) { save |= lang_str_set(&de->de_title, title, lang) ? DVR_UPDATED_TITLE : 0; } /* Subtitle */ - if (e && e->episode && e->episode->subtitle) { - save |= lang_str_set2(&de->de_subtitle, e->episode->subtitle) ? DVR_UPDATED_SUBTITLE : 0; + if (e &&& e->subtitle) { + save |= lang_str_set2(&de->de_subtitle, e->subtitle) ? DVR_UPDATED_SUBTITLE : 0; } else if (subtitle) { save |= lang_str_set(&de->de_subtitle, subtitle, lang) ? DVR_UPDATED_SUBTITLE : 0; } /* Summary */ - if (e && e->episode && e->episode->summary) { - save |= lang_str_set2(&de->de_summary, e->episode->summary) ? DVR_UPDATED_SUMMARY : 0; + if (e && e->summary) { + save |= lang_str_set2(&de->de_summary, e->summary) ? DVR_UPDATED_SUMMARY : 0; } else if (summary) { save |= lang_str_set(&de->de_summary, summary, lang) ? DVR_UPDATED_SUMMARY : 0; } @@ -2095,19 +2090,15 @@ static dvr_entry_t *_dvr_entry_update /* Description */ if (e && e->description) { save |= lang_str_set2(&de->de_desc, e->description) ? DVR_UPDATED_DESCRIPTION : 0; - } else if (e && e->episode && e->episode->description) { - save |= lang_str_set2(&de->de_desc, e->episode->description) ? DVR_UPDATED_DESCRIPTION : 0; } else if (e && e->summary) { save |= lang_str_set2(&de->de_desc, e->summary) ? DVR_UPDATED_DESCRIPTION : 0; - } else if (e && e->episode && e->episode->summary) { - save |= lang_str_set2(&de->de_desc, e->episode->summary) ? DVR_UPDATED_DESCRIPTION : 0; } else if (desc) { save |= lang_str_set(&de->de_desc, desc, lang) ? DVR_UPDATED_DESCRIPTION : 0; } /* Genre */ - if (e && e->episode) { - epg_genre_t *g = LIST_FIRST(&e->episode->genre); + if (e) { + epg_genre_t *g = LIST_FIRST(&e->genre); if (g && (g->code / 16) != de->de_content_type) { de->de_content_type = g->code / 16; save |= DVR_UPDATED_GENRE; @@ -2121,8 +2112,8 @@ static dvr_entry_t *_dvr_entry_update } /* Episode */ - if (de->de_bcast->episode) { - epg_episode_get_epnum(de->de_bcast->episode, &epnum); + if (de->de_bcast) { + epg_broadcast_get_epnum(de->de_bcast, &epnum); } else { memset(&epnum, 0, sizeof(epnum)); } @@ -3260,8 +3251,8 @@ dvr_entry_class_disp_episode_get(void *o) lang = idnode_lang(o); snprintf(buf1, sizeof(buf1), "%s %%d", tvh_gettext_lang(lang, N_("Season"))); snprintf(buf2, sizeof(buf2), "%s %%d", tvh_gettext_lang(lang, N_("Episode"))); - epg_episode_epnum_format(&de->de_epnum, prop_sbuf, PROP_SBUF_LEN, NULL, - buf1, ".", buf2, "/%d"); + epg_episode_num_format(&de->de_epnum, prop_sbuf, PROP_SBUF_LEN, NULL, + buf1, ".", buf2, "/%d"); return &prop_sbuf_ptr; } else if (de->de_epnum.text) { prop_ptr = de->de_epnum.text; @@ -3374,8 +3365,8 @@ dvr_entry_class_image_url_get_as_property(void *o) * future may have a generic image that will be updated nearer the * broadcast date with a more specific image. */ - if (de->de_bcast && de->de_bcast->episode && de->de_bcast->episode->image) { - snprintf(prop_sbuf, PROP_SBUF_LEN, "%s", de->de_bcast->episode->image); + if (de->de_bcast && de->de_bcast && de->de_bcast->image) { + snprintf(prop_sbuf, PROP_SBUF_LEN, "%s", de->de_bcast->image); return &prop_sbuf_ptr; } @@ -3414,8 +3405,7 @@ dvr_entry_class_first_aired_get(void *o) { static time_t null = 0; const dvr_entry_t *de = (const dvr_entry_t *)o; - return de && de->de_bcast && de->de_bcast->episode ? - &de->de_bcast->episode->first_aired : &null; + return de && de->de_bcast ? &de->de_bcast->first_aired : &null; } static const void * @@ -3462,9 +3452,9 @@ dvr_entry_class_genre_get(void *o) { const dvr_entry_t *de = (dvr_entry_t *)o; htsmsg_t *l = htsmsg_create_list(); - if (de->de_bcast && de->de_bcast->episode) { + if (de->de_bcast && de->de_bcast) { epg_genre_t *eg; - LIST_FOREACH(eg, &de->de_bcast->episode->genre, link) { + LIST_FOREACH(eg, &de->de_bcast->genre, link) { htsmsg_add_u32(l, NULL, eg->code); } } diff --git a/src/dvr/dvr_rec.c b/src/dvr/dvr_rec.c index 9cb7a91cd..5f54c59dd 100644 --- a/src/dvr/dvr_rec.c +++ b/src/dvr/dvr_rec.c @@ -369,11 +369,11 @@ dvr_sub_episode(const char *id, const char *fmt, const void *aux, char *tmp, siz const dvr_entry_t *de = aux; char buf[64]; - if (de->de_bcast == NULL || de->de_bcast->episode == NULL) + if (de->de_bcast == NULL) return ""; - epg_episode_number_format(de->de_bcast->episode, - buf, sizeof(buf), - NULL, "S%02d", NULL, "E%02d", NULL); + epg_broadcast_epnumber_format(de->de_bcast, + buf, sizeof(buf), + NULL, "S%02d", NULL, "E%02d", NULL); return dvr_do_prefix(id, fmt, buf, tmp, tmplen); } @@ -383,8 +383,7 @@ _dvr_sub_scraper_friendly(const char *id, const char *fmt, const void *aux, char char date_buf[512] = { 0 }; char episode_buf[512] = { 0 }; const dvr_entry_t *de = aux; - /* Can't be const due to call to epg_episode_number_format */ - /*const*/ epg_episode_t *episode = de->de_bcast ? de->de_bcast->episode : 0; + epg_broadcast_t *ebc = de->de_bcast; *tmp = 0; const char *title = lang_str_get(de->de_title, NULL); @@ -433,11 +432,11 @@ _dvr_sub_scraper_friendly(const char *id, const char *fmt, const void *aux, char else if (fmt && *fmt == '2') /* Force to be a series (not a movie) */ is_movie = 0; else { - if (de->de_bcast && de->de_bcast->category) { + if (ebc && ebc->category) { /* We've parsed categories from xmltv. So check if it has the movie category. */ is_movie = - string_list_contains_string(de->de_bcast->category, "movie") || - string_list_contains_string(de->de_bcast->category, "film"); + string_list_contains_string(ebc->category, "movie") || + string_list_contains_string(ebc->category, "film"); } else { /* No xmltv categories parsed. So have to use less-accurate genre instead. */ @@ -449,7 +448,7 @@ _dvr_sub_scraper_friendly(const char *id, const char *fmt, const void *aux, char * series/episode number then assume must be an episode, * otherwise we default to movie. */ - if (episode && (episode->epnum.s_num || episode->epnum.e_num)) + if (ebc && (ebc->epnum.s_num || ebc->epnum.e_num)) is_movie = 0; } } @@ -461,12 +460,12 @@ _dvr_sub_scraper_friendly(const char *id, const char *fmt, const void *aux, char /* Include the year if available. This helps scraper differentiate * between numerous remakes of the same film. */ - if (episode) { - if (episode->copyright_year) { - sprintf(date_buf, "%04d", episode->copyright_year); + if (ebc) { + if (ebc->copyright_year) { + sprintf(date_buf, "%04d", ebc->copyright_year); } else { /* Some providers use first_aired as really the copyright date. */ - const time_t first_aired = episode->first_aired; + const time_t first_aired = ebc->first_aired; if (first_aired) { /* Get just the year part */ struct tm tm; @@ -478,13 +477,13 @@ _dvr_sub_scraper_friendly(const char *id, const char *fmt, const void *aux, char } } else { /* Not a movie */ - if (episode) { + if (ebc) { /* Get episode information */ - epg_episode_number_format(episode, - episode_buf, sizeof(episode_buf), - NULL, "S%02d", NULL, "E%02d", NULL); + epg_broadcast_epnumber_format(ebc, + episode_buf, sizeof(episode_buf), + NULL, "S%02d", NULL, "E%02d", NULL); - const time_t first_aired = episode->first_aired; + const time_t first_aired = ebc->first_aired; if (first_aired) { /* Get as yyyy-mm-dd since programme could be one episode a day/week, * unlike films which only needs the year. @@ -584,9 +583,9 @@ dvr_sub_genre(const char *id, const char *fmt, const void *aux, char *tmp, size_ epg_genre_t *genre; char buf[64]; - if (de->de_bcast == NULL || de->de_bcast->episode == NULL) + if (de->de_bcast == NULL) return ""; - genre = LIST_FIRST(&de->de_bcast->episode->genre); + genre = LIST_FIRST(&de->de_bcast->genre); if (!genre || !genre->code) return ""; epg_genre_get_str(genre, 0, 1, buf, sizeof(buf), "en"); diff --git a/src/epg.c b/src/epg.c index 0fe21dcfa..3325b5e1b 100644 --- a/src/epg.c +++ b/src/epg.c @@ -73,11 +73,6 @@ static int _id_cmp ( const void *a, const void *b ) return ((epg_object_t*)a)->id - ((epg_object_t*)b)->id; } -static int _uri_cmp ( const void *a, const void *b ) -{ - return strcmp(((epg_object_t*)a)->uri, ((epg_object_t*)b)->uri); -} - static int _ebc_start_cmp ( const void *a, const void *b ) { return ((epg_broadcast_t*)a)->start - ((epg_broadcast_t*)b)->start; @@ -92,7 +87,7 @@ void epg_updated ( void ) /* Remove unref'd */ while ((eo = LIST_FIRST(&epg_object_unref))) { tvhtrace(LS_EPG, - "unref'd object %u (%s) created during update", eo->id, eo->uri); + "unref'd object %u created during update", eo->id); LIST_REMOVE(eo, un_link); eo->ops->destroy(eo); } @@ -117,9 +112,8 @@ static void _epg_object_destroy ( epg_object_t *eo, epg_object_tree_t *tree ) { assert(eo->refcount == 0); - tvhtrace(LS_EPG, "eo [%p, %u, %d, %s] destroy", - eo, eo->id, eo->type, eo->uri); - if (eo->uri) free(eo->uri); + tvhtrace(LS_EPG, "eo [%p, %u, %d] destroy", + eo, eo->id, eo->type); if (tree) RB_REMOVE(tree, eo, uri_link); if (eo->_updated) LIST_REMOVE(eo, up_link); RB_REMOVE(epg_id_tree(eo), eo, id_link); @@ -128,8 +122,8 @@ static void _epg_object_destroy static void _epg_object_getref ( void *o ) { epg_object_t *eo = o; - tvhtrace(LS_EPG, "eo [%p, %u, %d, %s] getref %d", - eo, eo->id, eo->type, eo->uri, eo->refcount+1); + tvhtrace(LS_EPG, "eo [%p, %u, %d] getref %d", + eo, eo->id, eo->type, eo->refcount+1); if (eo->refcount == 0) LIST_REMOVE(eo, un_link); eo->refcount++; } @@ -137,8 +131,8 @@ static void _epg_object_getref ( void *o ) static int _epg_object_putref ( void *o ) { epg_object_t *eo = o; - tvhtrace(LS_EPG, "eo [%p, %u, %d, %s] putref %d", - eo, eo->id, eo->type, eo->uri, eo->refcount-1); + tvhtrace(LS_EPG, "eo [%p, %u, %d] putref %d", + eo, eo->id, eo->type, eo->refcount-1); assert(eo->refcount>0); eo->refcount--; if (!eo->refcount) { @@ -151,8 +145,8 @@ static int _epg_object_putref ( void *o ) static void _epg_object_set_updated0 ( void *o ) { epg_object_t *eo = o; - tvhtrace(LS_EPG, "eo [%p, %u, %d, %s] updated", - eo, eo->id, eo->type, eo->uri); + tvhtrace(LS_EPG, "eo [%p, %u, %d] updated", + eo, eo->id, eo->type); eo->_updated = 1; eo->updated = gclk(); LIST_INSERT_HEAD(&epg_object_updated, eo, up_link); @@ -192,8 +186,8 @@ static void _epg_object_create ( void *o ) uint32_t id = eo->id; if (!id) eo->id = ++_epg_object_idx; if (!eo->id) eo->id = ++_epg_object_idx; - tvhtrace(LS_EPG, "eo [%p, %u, %d, %s] created", - eo, eo->id, eo->type, eo->uri); + tvhtrace(LS_EPG, "eo [%p, %u, %d] created", + eo, eo->id, eo->type); _epg_object_set_updated(eo); LIST_INSERT_HEAD(&epg_object_unref, eo, un_link); while (1) { @@ -208,41 +202,6 @@ static void _epg_object_create ( void *o ) } } -static epg_object_t *_epg_object_find_by_uri - ( const char *uri, epggrab_module_t *src, int create, int *save, - uint32_t *changes, epg_object_tree_t *tree, epg_object_t **skel ) -{ - epg_object_t *eo; - int _save; - - assert(skel != NULL); - lock_assert(&global_lock); - - (*skel)->uri = (char*)uri; - - /* Find only */ - if (!create) { - eo = RB_FIND(tree, *skel, uri_link, _uri_cmp); - - /* Find/create */ - } else { - eo = RB_INSERT_SORTED(tree, *skel, uri_link, _uri_cmp); - if (!eo) { - if (changes) *changes |= EPG_CHANGED_CREATE; - *save = 1; - eo = *skel; - *skel = NULL; - eo->uri = strdup(uri); - _epg_object_create(eo); - } - } - if (eo) { - _save = _epg_object_set_grabber(eo, src); - if (save) *save |= _save; - } - return eo; -} - epg_object_t *epg_object_find_by_id ( uint32_t id, epg_object_type_t type ) { epg_object_t *eo, temp; @@ -257,14 +216,12 @@ static htsmsg_t * _epg_object_serialize ( void *o ) { htsmsg_t *m; epg_object_t *eo = o; - tvhtrace(LS_EPG, "eo [%p, %u, %d, %s] serialize", - eo, eo->id, eo->type, eo->uri); + tvhtrace(LS_EPG, "eo [%p, %u, %d] serialize", + eo, eo->id, eo->type); if (!eo->id || !eo->type) return NULL; m = htsmsg_create_map(); htsmsg_add_u32(m, "id", eo->id); htsmsg_add_u32(m, "type", eo->type); - if (eo->uri) - htsmsg_add_str(m, "uri", eo->uri); if (eo->grabber) htsmsg_add_str(m, "grabber", eo->grabber->id); htsmsg_add_s64(m, "updated", eo->updated); @@ -279,21 +236,20 @@ static epg_object_t *_epg_object_deserialize ( htsmsg_t *m, epg_object_t *eo ) if (htsmsg_get_u32(m, "id", &eo->id)) return NULL; if (htsmsg_get_u32(m, "type", &u32)) return NULL; if (u32 != eo->type) return NULL; - eo->uri = (char*)htsmsg_get_str(m, "uri"); if ((s = htsmsg_get_str(m, "grabber"))) eo->grabber = epggrab_module_find_by_id(s); if (!htsmsg_get_s64(m, "updated", &s64)) { _epg_object_set_updated(eo); eo->updated = s64; } - tvhtrace(LS_EPG, "eo [%p, %u, %d, %s, %s, %s] deserialize", - eo, eo->id, eo->type, eo->uri, s, eo->grabber ? eo->grabber->id : NULL); + tvhtrace(LS_EPG, "eo [%p, %u, %d, %s, %s] deserialize", + eo, eo->id, eo->type, s, eo->grabber ? eo->grabber->id : NULL); return eo; } static int _epg_object_set_str ( void *o, char **old, const char *newstr, - uint32_t *changed, uint32_t cflag ) + epg_changes_t *changed, epg_changes_t cflag ) { int save = 0; epg_object_t *eo = o; @@ -313,7 +269,7 @@ static int _epg_object_set_str #define EPG_OBJECT_SET_FN(FNNAME,TYPE,DESTROY,COMPARE,COPY) \ static int FNNAME \ ( void *o, TYPE **old, const TYPE *new, \ - uint32_t *changed, uint32_t cflag ) \ + epg_changes_t *changed, epg_changes_t cflag ) \ { \ if (!o) return 0; \ if (changed) *changed |= cflag; \ @@ -344,7 +300,7 @@ EPG_OBJECT_SET_FN(_epg_object_set_htsmsg, htsmsg_t, htsmsg_destroy, #define EPG_OBJECT_SET_FN(FNNAME,TYPE) \ static int FNNAME \ ( void *o, TYPE *old, const TYPE nval, \ - uint32_t *changed, uint32_t cflag ) \ + epg_changes_t *changed, epg_changes_t cflag ) \ { \ int save; \ if (!o) return 0; \ @@ -364,8 +320,6 @@ htsmsg_t *epg_object_serialize ( epg_object_t *eo ) { if (!eo) return NULL; switch (eo->type) { - case EPG_EPISODE: - return epg_episode_serialize((epg_episode_t*)eo); case EPG_BROADCAST: return epg_broadcast_serialize((epg_broadcast_t*)eo); default: @@ -379,8 +333,6 @@ epg_object_t *epg_object_deserialize ( htsmsg_t *msg, int create, int *save ) if (!msg) return NULL; type = htsmsg_get_u32_or_default(msg, "type", 0); switch (type) { - case EPG_EPISODE: - return (epg_object_t*)epg_episode_deserialize(msg, create, save); case EPG_BROADCAST: return (epg_object_t*)epg_broadcast_deserialize(msg, create, save); } @@ -438,318 +390,7 @@ void epg_episode_epnum_deserialize num->text = strdup(str); } -static void _epg_episode_destroy ( void *eo ) -{ - epg_genre_t *g; - epg_episode_t *ee = eo; - if (LIST_FIRST(&ee->broadcasts)) { - tvhlog(LOG_CRIT, LS_EPG, "attempt to destroy episode with broadcasts"); - assert(0); - } - if (ee->title) lang_str_destroy(ee->title); - if (ee->subtitle) lang_str_destroy(ee->subtitle); - if (ee->summary) lang_str_destroy(ee->summary); - if (ee->description) lang_str_destroy(ee->description); - while ((g = LIST_FIRST(&ee->genre))) { - LIST_REMOVE(g, link); - free(g); - } - if (ee->image) free(ee->image); - if (ee->epnum.text) free(ee->epnum.text); - _epg_object_destroy(eo, &epg_episodes); - free(ee); -} - -static void _epg_episode_updated ( void *eo ) -{ -} - -static epg_object_ops_t _epg_episode_ops = { - .getref = _epg_object_getref, - .putref = _epg_object_putref, - .destroy = _epg_episode_destroy, - .update = _epg_episode_updated, -}; - -static epg_object_t **_epg_episode_skel ( void ) -{ - static epg_object_t *skel = NULL; - if (!skel) { - skel = calloc(1, sizeof(epg_episode_t)); - skel->type = EPG_EPISODE; - skel->ops = &_epg_episode_ops; - } - return &skel; -} - -epg_episode_t* epg_episode_find_by_uri - ( const char *uri, epggrab_module_t *src, int create, - int *save, uint32_t *changed ) -{ - return (epg_episode_t*) - _epg_object_find_by_uri(uri, src, create, save, changed, - &epg_episodes, - _epg_episode_skel()); -} - -epg_episode_t *epg_episode_find_by_id ( uint32_t id ) -{ - return (epg_episode_t*)epg_object_find_by_id(id, EPG_EPISODE); -} - -epg_episode_t *epg_episode_find_by_broadcast - ( epg_broadcast_t *ebc, epggrab_module_t *src, - int create, int *save, uint32_t *changed ) -{ - char uri[UUID_HEX_SIZE+50], ubuf[UUID_HEX_SIZE]; - if (!ebc) return NULL; - if (ebc->episode) { - _epg_object_set_grabber(ebc->episode, src); - return ebc->episode; - } - if (!create) return NULL; - snprintf(uri, sizeof(uri)-1, "tvh://channel-%s/bcast-%u/episode", - idnode_uuid_as_str(&ebc->channel->ch_id, ubuf), ebc->id); - return epg_episode_find_by_uri(uri, src, 1, save, changed); -} - -int epg_episode_change_finish - ( epg_episode_t *episode, uint32_t changes, int merge ) -{ - int save = 0; - if (merge) return 0; - if (changes & EPG_CHANGED_CREATE) return 0; - if (!(changes & EPG_CHANGED_TITLE)) - save |= epg_episode_set_title(episode, NULL, NULL); - if (!(changes & EPG_CHANGED_SUBTITLE)) - save |= epg_episode_set_subtitle(episode, NULL, NULL); - if (!(changes & EPG_CHANGED_SUMMARY)) - save |= epg_episode_set_summary(episode, NULL, NULL); - if (!(changes & EPG_CHANGED_DESCRIPTION)) - save |= epg_episode_set_description(episode, NULL, NULL); - if (!(changes & EPG_CHANGED_IMAGE)) - save |= epg_episode_set_image(episode, NULL, NULL); - if (!(changes & EPG_CHANGED_EPSER_NUM)) - save |= _epg_object_set_u16(episode, &episode->epnum.s_num, 0, NULL, 0); - if (!(changes & EPG_CHANGED_EPSER_CNT)) - save |= _epg_object_set_u16(episode, &episode->epnum.s_cnt, 0, NULL, 0); - if (!(changes & EPG_CHANGED_EPNUM_NUM)) - save |= _epg_object_set_u16(episode, &episode->epnum.e_num, 0, NULL, 0); - if (!(changes & EPG_CHANGED_EPNUM_CNT)) - save |= _epg_object_set_u16(episode, &episode->epnum.e_cnt, 0, NULL, 0); - if (!(changes & EPG_CHANGED_EPPAR_NUM)) - save |= _epg_object_set_u16(episode, &episode->epnum.p_num, 0, NULL, 0); - if (!(changes & EPG_CHANGED_EPPAR_CNT)) - save |= _epg_object_set_u16(episode, &episode->epnum.p_cnt, 0, NULL, 0); - if (!(changes & EPG_CHANGED_EPTEXT)) - save |= _epg_object_set_str(episode, &episode->epnum.text, NULL, NULL, 0); - if (!(changes & EPG_CHANGED_GENRE)) - save |= epg_episode_set_genre(episode, NULL, NULL); - if (!(changes & EPG_CHANGED_IS_BW)) - save |= epg_episode_set_is_bw(episode, 0, NULL); - if (!(changes & EPG_CHANGED_STAR_RATING)) - save |= epg_episode_set_star_rating(episode, 0, NULL); - if (!(changes & EPG_CHANGED_AGE_RATING)) - save |= epg_episode_set_age_rating(episode, 0, NULL); - if (!(changes & EPG_CHANGED_FIRST_AIRED)) - save |= epg_episode_set_first_aired(episode, 0, NULL); - if (!(changes & EPG_CHANGED_COPYRIGHT_YEAR)) - save |= epg_episode_set_copyright_year(episode, 0, NULL); - return save; -} - -int epg_episode_set_title - ( epg_episode_t *episode, const lang_str_t *title, uint32_t *changed ) -{ - if (!episode) return 0; - return _epg_object_set_lang_str(episode, &episode->title, title, - changed, EPG_CHANGED_TITLE); -} - -int epg_episode_set_subtitle - ( epg_episode_t *episode, const lang_str_t *subtitle, uint32_t *changed ) -{ - if (!episode) return 0; - return _epg_object_set_lang_str(episode, &episode->subtitle, - subtitle, changed, EPG_CHANGED_SUBTITLE); -} - -int epg_episode_set_summary - ( epg_episode_t *episode, const lang_str_t *summary, uint32_t *changed ) -{ - if (!episode) return 0; - return _epg_object_set_lang_str(episode, &episode->summary, - summary, changed, EPG_CHANGED_SUMMARY); -} - -int epg_episode_set_description - ( epg_episode_t *episode, const lang_str_t *desc, uint32_t *changed ) -{ - if (!episode) return 0; - return _epg_object_set_lang_str(episode, &episode->description, - desc, changed, EPG_CHANGED_DESCRIPTION); -} - -int epg_episode_set_image - ( epg_episode_t *episode, const char *image, uint32_t *changed ) -{ - int save; - if (!episode) return 0; - save = _epg_object_set_str(episode, &episode->image, image, - changed, EPG_CHANGED_IMAGE); - if (save) - imagecache_get_id(image); - return save; -} - -int epg_episode_set_number - ( epg_episode_t *episode, uint16_t number, uint32_t *changed ) -{ - if (!episode) return 0; - return _epg_object_set_u16(episode, &episode->epnum.e_num, number, - changed, EPG_CHANGED_EPNUM_NUM); -} - -int epg_episode_set_part - ( epg_episode_t *episode, uint16_t part, uint16_t count, - uint32_t *changed ) -{ - int save = 0; - if (!episode) return 0; - save |= _epg_object_set_u16(episode, &episode->epnum.p_num, part, - changed, EPG_CHANGED_EPPAR_NUM); - save |= _epg_object_set_u16(episode, &episode->epnum.p_cnt, count, - changed, EPG_CHANGED_EPPAR_CNT); - return save; -} - -int epg_episode_set_epnum - ( epg_episode_t *episode, epg_episode_num_t *num, uint32_t *changed ) -{ - int save = 0; - static epg_episode_num_t _zero = { 0 }; - if (!episode) - return 0; - if (!num) - num = &_zero; - if (num->s_num) - save |= _epg_object_set_u16(episode, &episode->epnum.s_num, - num->s_num, changed, EPG_CHANGED_EPSER_NUM); - if (num->s_cnt) - save |= _epg_object_set_u16(episode, &episode->epnum.s_cnt, - num->s_cnt, changed, EPG_CHANGED_EPSER_CNT); - if (num->e_num) - save |= _epg_object_set_u16(episode, &episode->epnum.e_num, - num->e_num, changed, EPG_CHANGED_EPNUM_NUM); - if (num->e_cnt) - save |= _epg_object_set_u16(episode, &episode->epnum.e_cnt, - num->e_cnt, changed, EPG_CHANGED_EPNUM_CNT); - if (num->p_num) - save |= _epg_object_set_u16(episode, &episode->epnum.p_num, - num->p_num, changed, EPG_CHANGED_EPPAR_NUM); - if (num->p_cnt) - save |= _epg_object_set_u16(episode, &episode->epnum.p_cnt, - num->p_cnt, changed, EPG_CHANGED_EPPAR_CNT); - if (num->text) - save |= _epg_object_set_str(episode, &episode->epnum.text, - num->text, changed, EPG_CHANGED_EPTEXT); - return save; -} - -int epg_episode_set_genre - ( epg_episode_t *ee, epg_genre_list_t *genre, uint32_t *changed ) -{ - int save = 0; - epg_genre_t *g1, *g2; - - if (!ee) return 0; - - if (changed) *changed |= EPG_CHANGED_GENRE; - - g1 = LIST_FIRST(&ee->genre); - - /* Remove old */ - while (g1) { - g2 = LIST_NEXT(g1, link); - if (!epg_genre_list_contains(genre, g1, 0)) { - LIST_REMOVE(g1, link); - free(g1); - save = 1; - } - g1 = g2; - } - - /* Insert all entries */ - if (genre) { - LIST_FOREACH(g1, genre, link) - save |= epg_genre_list_add(&ee->genre, g1); - } - - return save; -} - -int epg_episode_set_is_bw - ( epg_episode_t *episode, uint8_t bw, uint32_t *changed ) -{ - if (!episode) return 0; - return _epg_object_set_u8(episode, &episode->is_bw, bw, - changed, EPG_CHANGED_IS_BW); -} - -int epg_episode_set_star_rating - ( epg_episode_t *episode, uint8_t stars, uint32_t *changed ) -{ - if (!episode) return 0; - return _epg_object_set_u8(episode, &episode->star_rating, stars, - changed, EPG_CHANGED_STAR_RATING); -} - -int epg_episode_set_copyright_year - ( epg_episode_t *episode, uint16_t year, uint32_t *changed ) -{ - if (!episode) return 0; - return _epg_object_set_u16(episode, &episode->copyright_year, year, - changed, EPG_CHANGED_COPYRIGHT_YEAR); -} - -int epg_episode_set_age_rating - ( epg_episode_t *episode, uint8_t age, uint32_t *changed ) -{ - if (!episode) return 0; - return _epg_object_set_u8(episode, &episode->age_rating, age, - changed, EPG_CHANGED_AGE_RATING); -} - -int epg_episode_set_first_aired - ( epg_episode_t *episode, time_t aired, uint32_t *changed ) -{ - if (!episode) return 0; - if (changed) *changed |= EPG_CHANGED_FIRST_AIRED; - if (episode->first_aired != aired) { - episode->first_aired = aired; - _epg_object_set_updated(episode); - return 1; - } - return 0; -} - -static void _epg_episode_add_broadcast - ( epg_episode_t *episode, epg_broadcast_t *broadcast ) -{ - _epg_object_getref(episode); - _epg_object_set_updated(episode); - LIST_INSERT_SORTED(&episode->broadcasts, broadcast, ep_link, _ebc_start_cmp); -} - -static void _epg_episode_rem_broadcast - ( epg_episode_t *episode, epg_broadcast_t *broadcast ) -{ - LIST_REMOVE(broadcast, ep_link); - _epg_object_set_updated(episode); - _epg_object_putref(episode); -} - -size_t epg_episode_epnum_format +size_t epg_episode_num_format ( epg_episode_num_t *epnum, char *buf, size_t len, const char *pre, const char *sfmt, const char *sep, const char *efmt, @@ -776,29 +417,6 @@ size_t epg_episode_epnum_format return i; } -size_t epg_episode_number_format - ( epg_episode_t *episode, char *buf, size_t len, - const char *pre, const char *sfmt, - const char *sep, const char *efmt, - const char *cfmt ) -{ - if (!episode) return 0; - epg_episode_num_t num; - epg_episode_get_epnum(episode, &num); - return epg_episode_epnum_format(&num, buf, len, pre, - sfmt, sep, efmt, cfmt); -} - -void epg_episode_get_epnum ( const epg_episode_t *ee, epg_episode_num_t *num ) -{ - if (!ee || !num) { - if (num) - memset(num, 0, sizeof(*num)); - return; - } - *num = ee->epnum; -} - int epg_episode_number_cmp ( const epg_episode_num_t *a, const epg_episode_num_t *b ) { if (a->e_num) { @@ -832,157 +450,6 @@ int epg_episode_number_cmpfull ( const epg_episode_num_t *a, const epg_episode_n return strcasecmp(a->text ?: "", b->text ?: ""); } -// WIBNI: this could do with soem proper matching, maybe some form of -// fuzzy string match. I did try a few things, but none of them -// were very reliable. -#if TODO_FUZZY_MATCH -int epg_episode_fuzzy_match - ( epg_episode_t *episode, const char *uri, const char *title, - const char *summary, const char *description ) -{ - if (!episode) return 0; - if (uri && episode->uri && !strcmp(episode->uri, uri)) return 1; - if (title && episode->title && (strstr(title, episode->title) || strstr(episode->title, title))) return 1; - return 0; -} -#endif - -htsmsg_t *epg_episode_serialize ( epg_episode_t *episode ) -{ - epg_genre_t *eg; - htsmsg_t *m, *a = NULL; - if (!episode || !episode->uri) return NULL; - if (!(m = _epg_object_serialize((epg_object_t*)episode))) return NULL; - if (episode->title) - lang_str_serialize(episode->title, m, "title"); - if (episode->subtitle) - lang_str_serialize(episode->subtitle, m, "subtitle"); - if (episode->summary) - lang_str_serialize(episode->summary, m, "summary"); - if (episode->description) - lang_str_serialize(episode->description, m, "description"); - htsmsg_add_msg(m, "epnum", epg_episode_epnum_serialize(&episode->epnum)); - LIST_FOREACH(eg, &episode->genre, link) { - if (!a) a = htsmsg_create_list(); - htsmsg_add_u32(a, NULL, eg->code); - } - if (a) htsmsg_add_msg(m, "genre", a); - if (episode->is_bw) - htsmsg_add_u32(m, "is_bw", 1); - if (episode->star_rating) - htsmsg_add_u32(m, "star_rating", episode->star_rating); - if (episode->copyright_year) - htsmsg_add_u32(m, "copyright_year", episode->copyright_year); - if (episode->age_rating) - htsmsg_add_u32(m, "age_rating", episode->age_rating); - if (episode->first_aired) - htsmsg_add_s64(m, "first_aired", episode->first_aired); - if (episode->image) - htsmsg_add_str(m, "image", episode->image); - - return m; -} - -epg_episode_t *epg_episode_deserialize ( htsmsg_t *m, int create, int *save ) -{ - epg_object_t **skel = _epg_episode_skel(); - epg_episode_t *ee; - const char *str; - epg_episode_num_t num; - htsmsg_t *sub; - htsmsg_field_t *f; - uint32_t u32, changes = 0; - int64_t s64; - lang_str_t *ls; - - if (!_epg_object_deserialize(m, *skel)) return NULL; - if (!(ee = epg_episode_find_by_uri((*skel)->uri, (*skel)->grabber, - create, save, &changes))) - return NULL; - - if ((ls = lang_str_deserialize(m, "title"))) { - *save |= epg_episode_set_title(ee, ls, &changes); - lang_str_destroy(ls); - } - if ((ls = lang_str_deserialize(m, "subtitle"))) { - *save |= epg_episode_set_subtitle(ee, ls, &changes); - lang_str_destroy(ls); - } - if ((ls = lang_str_deserialize(m, "summary"))) { - *save |= epg_episode_set_summary(ee, ls, &changes); - lang_str_destroy(ls); - } - if ((ls = lang_str_deserialize(m, "description"))) { - *save |= epg_episode_set_description(ee, ls, &changes); - lang_str_destroy(ls); - } - if ((sub = htsmsg_get_map(m, "epnum"))) { - epg_episode_epnum_deserialize(sub, &num); - *save |= epg_episode_set_epnum(ee, &num, &changes); - if (num.text) free(num.text); - } - if ((sub = htsmsg_get_list(m, "genre"))) { - epg_genre_list_t *egl = calloc(1, sizeof(epg_genre_list_t)); - HTSMSG_FOREACH(f, sub) { - epg_genre_t genre; - genre.code = (uint8_t)f->hmf_s64; - epg_genre_list_add(egl, &genre); - } - *save |= epg_episode_set_genre(ee, egl, &changes); - epg_genre_list_destroy(egl); - } - - if (!htsmsg_get_u32(m, "is_bw", &u32)) - *save |= epg_episode_set_is_bw(ee, u32, &changes); - - if (!htsmsg_get_u32(m, "star_rating", &u32)) - *save |= epg_episode_set_star_rating(ee, u32, &changes); - - if (!htsmsg_get_u32(m, "copyright_year", &u32)) - *save |= epg_episode_set_copyright_year(ee, u32, &changes); - - if (!htsmsg_get_u32(m, "age_rating", &u32)) - *save |= epg_episode_set_age_rating(ee, u32, &changes); - - if (!htsmsg_get_s64(m, "first_aired", &s64)) - *save |= epg_episode_set_first_aired(ee, (time_t)s64, &changes); - - if ((str = htsmsg_get_str(m, "image"))) - *save |= epg_episode_set_image(ee, str, &changes); - - *save |= epg_episode_change_finish(ee, changes, 0); - - return ee; -} - -const char *epg_episode_get_title - ( const epg_episode_t *e, const char *lang ) -{ - if (!e || !e->title) return NULL; - return lang_str_get(e->title, lang); -} - -const char *epg_episode_get_subtitle - ( const epg_episode_t *e, const char *lang ) -{ - if (!e || !e->subtitle) return NULL; - return lang_str_get(e->subtitle, lang); -} - -const char *epg_episode_get_summary - ( const epg_episode_t *e, const char *lang ) -{ - if (!e || !e->summary) return NULL; - return lang_str_get(e->summary, lang); -} - -const char *epg_episode_get_description - ( const epg_episode_t *e, const char *lang ) -{ - if (!e || !e->description) return NULL; - return lang_str_get(e->description, lang); -} - /* ************************************************************************** * Channel * *************************************************************************/ @@ -1071,7 +538,7 @@ static void _epg_channel_timer_callback ( void *p ) static epg_broadcast_t *_epg_channel_add_broadcast ( channel_t *ch, epg_broadcast_t **bcast, epggrab_module_t *src, - int create, int *save, uint32_t *changed ) + int create, int *save, epg_changes_t *changed ) { int timer = 0; epg_broadcast_t *ebc, *ret; @@ -1256,12 +723,10 @@ static int epg_match_event_fuzzy(epg_broadcast_t *a, epg_broadcast_t *b) return 0; /* episode check */ - if (a->episode && b->episode) { - epg_episode_get_epnum(a->episode, &num1); - epg_episode_get_epnum(b->episode, &num2); - if (epg_episode_number_cmp(&num1, &num2) == 0) - return 1; - } + epg_broadcast_get_epnum(a, &num1); + epg_broadcast_get_epnum(b, &num2); + if (epg_episode_number_cmp(&num1, &num2) == 0) + return 1; return 0; } @@ -1289,6 +754,7 @@ epg_broadcast_t *epg_match_now_next ( channel_t *ch, epg_broadcast_t *ebc ) static void _epg_broadcast_destroy ( void *eo ) { epg_broadcast_t *ebc = eo; + epg_genre_t *eg; char id[16]; if (ebc->_created) { @@ -1296,15 +762,23 @@ static void _epg_broadcast_destroy ( void *eo ) snprintf(id, sizeof(id), "%u", ebc->id); notify_delayed(id, "epg", "delete"); } - if (ebc->episode) _epg_episode_rem_broadcast(ebc->episode, ebc); + if (ebc->title) lang_str_destroy(ebc->summary); + if (ebc->subtitle) lang_str_destroy(ebc->subtitle); if (ebc->summary) lang_str_destroy(ebc->summary); if (ebc->description) lang_str_destroy(ebc->description); + while ((eg = LIST_FIRST(&ebc->genre))) { + LIST_REMOVE(eg, link); + free(eg); + } + free(ebc->image); + free(ebc->epnum.text); if (ebc->credits) htsmsg_destroy(ebc->credits); if (ebc->credits_cached) lang_str_destroy(ebc->credits_cached); if (ebc->category) string_list_destroy(ebc->category); if (ebc->keyword) string_list_destroy(ebc->keyword); if (ebc->keyword_cached) lang_str_destroy(ebc->keyword_cached); free(ebc->serieslink_uri); + free(ebc->episode_uri); _epg_object_destroy(eo, NULL); assert(LIST_EMPTY(&ebc->dvr_entries)); free(ebc); @@ -1378,7 +852,7 @@ static epg_broadcast_t **_epg_broadcast_skel ( void ) epg_broadcast_t *epg_broadcast_find_by_time ( channel_t *channel, epggrab_module_t *src, - time_t start, time_t stop, int create, int *save, uint32_t *changed ) + time_t start, time_t stop, int create, int *save, epg_changes_t *changed ) { epg_broadcast_t **ebc; if (!channel || !start || !stop) return NULL; @@ -1393,15 +867,15 @@ epg_broadcast_t *epg_broadcast_find_by_time } int epg_broadcast_change_finish - ( epg_broadcast_t *broadcast, uint32_t changes, int merge ) + ( epg_broadcast_t *broadcast, epg_changes_t changes, int merge ) { int save = 0; if (merge) return 0; if (changes & EPG_CHANGED_CREATE) return 0; - if (!(changes & EPG_CHANGED_EPISODE)) - save |= epg_broadcast_set_episode(broadcast, NULL, NULL); if (!(changes & EPG_CHANGED_SERIESLINK)) save |= epg_broadcast_set_serieslink_uri(broadcast, NULL, NULL); + if (!(changes & EPG_CHANGED_EPISODE)) + save |= epg_broadcast_set_episode_uri(broadcast, NULL, NULL); if (!(changes & EPG_CHANGED_DVB_EID)) save |= epg_broadcast_set_dvb_eid(broadcast, 0, NULL); if (!(changes & EPG_CHANGED_IS_WIDESCREEN)) @@ -1422,10 +896,42 @@ int epg_broadcast_change_finish save |= epg_broadcast_set_is_new(broadcast, 0, NULL); if (!(changes & EPG_CHANGED_IS_REPEAT)) save |= epg_broadcast_set_is_repeat(broadcast, 0, NULL); + if (!(changes & EPG_CHANGED_IS_BW)) + save |= epg_broadcast_set_is_bw(broadcast, 0, NULL); + if (!(changes & EPG_CHANGED_STAR_RATING)) + save |= epg_broadcast_set_star_rating(broadcast, 0, NULL); + if (!(changes & EPG_CHANGED_AGE_RATING)) + save |= epg_broadcast_set_age_rating(broadcast, 0, NULL); + if (!(changes & EPG_CHANGED_IMAGE)) + save |= epg_broadcast_set_image(broadcast, NULL, NULL); + if (!(changes & EPG_CHANGED_GENRE)) + save |= epg_broadcast_set_genre(broadcast, NULL, NULL); + if (!(changes & EPG_CHANGED_TITLE)) + save |= epg_broadcast_set_title(broadcast, NULL, NULL); + if (!(changes & EPG_CHANGED_SUBTITLE)) + save |= epg_broadcast_set_subtitle(broadcast, NULL, NULL); if (!(changes & EPG_CHANGED_SUMMARY)) save |= epg_broadcast_set_summary(broadcast, NULL, NULL); if (!(changes & EPG_CHANGED_DESCRIPTION)) save |= epg_broadcast_set_description(broadcast, NULL, NULL); + if (!(changes & EPG_CHANGED_EPSER_NUM)) + save |= _epg_object_set_u16(broadcast, &broadcast->epnum.s_num, 0, NULL, 0); + if (!(changes & EPG_CHANGED_EPSER_CNT)) + save |= _epg_object_set_u16(broadcast, &broadcast->epnum.s_cnt, 0, NULL, 0); + if (!(changes & EPG_CHANGED_EPNUM_NUM)) + save |= _epg_object_set_u16(broadcast, &broadcast->epnum.e_num, 0, NULL, 0); + if (!(changes & EPG_CHANGED_EPNUM_CNT)) + save |= _epg_object_set_u16(broadcast, &broadcast->epnum.e_cnt, 0, NULL, 0); + if (!(changes & EPG_CHANGED_EPPAR_NUM)) + save |= _epg_object_set_u16(broadcast, &broadcast->epnum.p_num, 0, NULL, 0); + if (!(changes & EPG_CHANGED_EPPAR_CNT)) + save |= _epg_object_set_u16(broadcast, &broadcast->epnum.p_cnt, 0, NULL, 0); + if (!(changes & EPG_CHANGED_EPTEXT)) + save |= _epg_object_set_str(broadcast, &broadcast->epnum.text, NULL, NULL, 0); + if (!(changes & EPG_CHANGED_FIRST_AIRED)) + save |= epg_broadcast_set_first_aired(broadcast, 0, NULL); + if (!(changes & EPG_CHANGED_COPYRIGHT_YEAR)) + save |= epg_broadcast_set_copyright_year(broadcast, 0, NULL); if (!(changes & EPG_CHANGED_CREDITS)) save |= epg_broadcast_set_credits(broadcast, NULL, NULL); if (!(changes & EPG_CHANGED_CATEGORY)) @@ -1439,7 +945,7 @@ epg_broadcast_t *epg_broadcast_clone ( channel_t *channel, epg_broadcast_t *src, int *save ) { epg_broadcast_t *ebc; - uint32_t changes = 0; + epg_changes_t changes = 0; if (!src) return NULL; ebc = epg_broadcast_find_by_time(channel, src->grabber, @@ -1449,6 +955,7 @@ epg_broadcast_t *epg_broadcast_clone /* Copy metadata */ *save |= epg_broadcast_set_is_widescreen(ebc, src->is_widescreen, &changes); *save |= epg_broadcast_set_is_hd(ebc, src->is_hd, &changes); + *save |= epg_broadcast_set_is_bw(ebc, src->is_bw, &changes); *save |= epg_broadcast_set_lines(ebc, src->lines, &changes); *save |= epg_broadcast_set_aspect(ebc, src->aspect, &changes); *save |= epg_broadcast_set_is_deafsigned(ebc, src->is_deafsigned, &changes); @@ -1456,13 +963,23 @@ epg_broadcast_t *epg_broadcast_clone *save |= epg_broadcast_set_is_audio_desc(ebc, src->is_audio_desc, &changes); *save |= epg_broadcast_set_is_new(ebc, src->is_new, &changes); *save |= epg_broadcast_set_is_repeat(ebc, src->is_repeat, &changes); + *save |= epg_broadcast_set_star_rating(ebc, src->star_rating, &changes); + *save |= epg_broadcast_set_age_rating(ebc, src->age_rating, &changes); + *save |= epg_broadcast_set_image(ebc, src->image, &changes); + *save |= epg_broadcast_set_genre(ebc, &src->genre, &changes); + *save |= epg_broadcast_set_title(ebc, src->title, &changes); + *save |= epg_broadcast_set_subtitle(ebc, src->subtitle, &changes); *save |= epg_broadcast_set_summary(ebc, src->summary, &changes); + *save |= epg_broadcast_set_description(ebc, src->description, &changes); + *save |= epg_broadcast_set_epnum(ebc, &src->epnum, &changes); *save |= epg_broadcast_set_credits(ebc, src->credits, &changes); *save |= epg_broadcast_set_category(ebc, src->category, &changes); *save |= epg_broadcast_set_keyword(ebc, src->keyword, &changes); *save |= epg_broadcast_set_description(ebc, src->description, &changes); *save |= epg_broadcast_set_serieslink_uri(ebc, src->serieslink_uri, &changes); - *save |= epg_broadcast_set_episode(ebc, src->episode, &changes); + *save |= epg_broadcast_set_episode_uri(ebc, src->episode_uri, &changes); + *save |= epg_broadcast_set_first_aired(ebc, src->first_aired, &changes); + *save |= epg_broadcast_set_copyright_year(ebc, src->copyright_year, &changes); _epg_object_set_grabber(ebc, src->grabber); *save |= epg_broadcast_change_finish(ebc, changes, 0); } @@ -1495,39 +1012,36 @@ int epg_broadcast_set_running return save; } -int epg_broadcast_set_episode - ( epg_broadcast_t *broadcast, epg_episode_t *episode, uint32_t *changed ) +int epg_broadcast_set_serieslink_uri + ( epg_broadcast_t *ebc, const char *uri, epg_changes_t *changed ) { int save = 0; - if (!broadcast) return 0; - if (changed) *changed |= EPG_CHANGED_EPISODE; - if (broadcast->episode != episode) { - if (broadcast->episode) - _epg_episode_rem_broadcast(broadcast->episode, broadcast); - broadcast->episode = episode; - if (episode) _epg_episode_add_broadcast(episode, broadcast); - _epg_object_set_updated(broadcast); + if (!ebc) return 0; + if (changed) *changed |= EPG_CHANGED_SERIESLINK; + if (strcmp(ebc->serieslink_uri ?: "", uri ?: "")) { + free(ebc->serieslink_uri); + ebc->serieslink_uri = strdup(uri); save = 1; } return save; } -int epg_broadcast_set_serieslink_uri - ( epg_broadcast_t *ebc, const char *uri, uint32_t *changed ) +int epg_broadcast_set_episode_uri + ( epg_broadcast_t *ebc, const char *uri, epg_changes_t *changed ) { int save = 0; if (!ebc) return 0; if (changed) *changed |= EPG_CHANGED_SERIESLINK; - if (strcmp(ebc->serieslink_uri ?: "", uri ?: "")) { - free(ebc->serieslink_uri); - ebc->serieslink_uri = strdup(uri); + if (strcmp(ebc->episode_uri ?: "", uri ?: "")) { + free(ebc->episode_uri); + ebc->episode_uri = strdup(uri); save = 1; } return save; } int epg_broadcast_set_dvb_eid - ( epg_broadcast_t *b, uint16_t dvb_eid, uint32_t *changed ) + ( epg_broadcast_t *b, uint16_t dvb_eid, epg_changes_t *changed ) { if (!b) return 0; return _epg_object_set_u16(b, &b->dvb_eid, dvb_eid, @@ -1535,7 +1049,7 @@ int epg_broadcast_set_dvb_eid } int epg_broadcast_set_is_widescreen - ( epg_broadcast_t *b, uint8_t ws, uint32_t *changed ) + ( epg_broadcast_t *b, uint8_t ws, epg_changes_t *changed ) { if (!b) return 0; return _epg_object_set_u8(b, &b->is_widescreen, ws, @@ -1543,7 +1057,7 @@ int epg_broadcast_set_is_widescreen } int epg_broadcast_set_is_hd - ( epg_broadcast_t *b, uint8_t hd, uint32_t *changed ) + ( epg_broadcast_t *b, uint8_t hd, epg_changes_t *changed ) { if (!b) return 0; return _epg_object_set_u8(b, &b->is_hd, hd, @@ -1551,7 +1065,7 @@ int epg_broadcast_set_is_hd } int epg_broadcast_set_lines - ( epg_broadcast_t *b, uint16_t lines, uint32_t *changed ) + ( epg_broadcast_t *b, uint16_t lines, epg_changes_t *changed ) { if (!b) return 0; return _epg_object_set_u16(b, &b->lines, lines, @@ -1559,7 +1073,7 @@ int epg_broadcast_set_lines } int epg_broadcast_set_aspect - ( epg_broadcast_t *b, uint16_t aspect, uint32_t *changed ) + ( epg_broadcast_t *b, uint16_t aspect, epg_changes_t *changed ) { if (!b) return 0; return _epg_object_set_u16(b, &b->aspect, aspect, @@ -1567,7 +1081,7 @@ int epg_broadcast_set_aspect } int epg_broadcast_set_is_deafsigned - ( epg_broadcast_t *b, uint8_t ds, uint32_t *changed ) + ( epg_broadcast_t *b, uint8_t ds, epg_changes_t *changed ) { if (!b) return 0; return _epg_object_set_u8(b, &b->is_deafsigned, ds, @@ -1575,7 +1089,7 @@ int epg_broadcast_set_is_deafsigned } int epg_broadcast_set_is_subtitled - ( epg_broadcast_t *b, uint8_t st, uint32_t *changed ) + ( epg_broadcast_t *b, uint8_t st, epg_changes_t *changed ) { if (!b) return 0; return _epg_object_set_u8(b, &b->is_subtitled, st, @@ -1583,7 +1097,7 @@ int epg_broadcast_set_is_subtitled } int epg_broadcast_set_is_audio_desc - ( epg_broadcast_t *b, uint8_t ad, uint32_t *changed ) + ( epg_broadcast_t *b, uint8_t ad, epg_changes_t *changed ) { if (!b) return 0; return _epg_object_set_u8(b, &b->is_audio_desc, ad, @@ -1591,7 +1105,7 @@ int epg_broadcast_set_is_audio_desc } int epg_broadcast_set_is_new - ( epg_broadcast_t *b, uint8_t n, uint32_t *changed ) + ( epg_broadcast_t *b, uint8_t n, epg_changes_t *changed ) { if (!b) return 0; return _epg_object_set_u8(b, &b->is_new, n, @@ -1599,15 +1113,47 @@ int epg_broadcast_set_is_new } int epg_broadcast_set_is_repeat - ( epg_broadcast_t *b, uint8_t r, uint32_t *changed ) + ( epg_broadcast_t *b, uint8_t r, epg_changes_t *changed ) { if (!b) return 0; return _epg_object_set_u8(b, &b->is_repeat, r, changed, EPG_CHANGED_IS_REPEAT); } +int epg_broadcast_set_is_bw + ( epg_broadcast_t *b, uint8_t bw, epg_changes_t *changed ) +{ + if (!b) return 0; + return _epg_object_set_u8(b, &b->is_bw, bw, + changed, EPG_CHANGED_IS_BW); +} + +int epg_broadcast_set_star_rating + ( epg_broadcast_t *b, uint8_t stars, epg_changes_t *changed ) +{ + if (!b) return 0; + return _epg_object_set_u8(b, &b->star_rating, stars, + changed, EPG_CHANGED_STAR_RATING); +} + +int epg_broadcast_set_title + ( epg_broadcast_t *b, const lang_str_t *title, epg_changes_t *changed ) +{ + if (!b) return 0; + return _epg_object_set_lang_str(b, &b->title, title, + changed, EPG_CHANGED_TITLE); +} + +int epg_broadcast_set_subtitle + ( epg_broadcast_t *b, const lang_str_t *subtitle, epg_changes_t *changed ) +{ + if (!b) return 0; + return _epg_object_set_lang_str(b, &b->subtitle, + subtitle, changed, EPG_CHANGED_SUBTITLE); +} + int epg_broadcast_set_summary - ( epg_broadcast_t *b, const lang_str_t *str, uint32_t *changed ) + ( epg_broadcast_t *b, const lang_str_t *str, epg_changes_t *changed ) { if (!b) return 0; return _epg_object_set_lang_str(b, &b->summary, str, @@ -1615,7 +1161,7 @@ int epg_broadcast_set_summary } int epg_broadcast_set_description - ( epg_broadcast_t *b, const lang_str_t *str, uint32_t *changed ) + ( epg_broadcast_t *b, const lang_str_t *str, epg_changes_t *changed ) { if (!b) return 0; return _epg_object_set_lang_str(b, &b->description, str, @@ -1623,7 +1169,7 @@ int epg_broadcast_set_description } int epg_broadcast_set_credits -( epg_broadcast_t *b, const htsmsg_t *credits, uint32_t *changed ) +( epg_broadcast_t *b, const htsmsg_t *credits, epg_changes_t *changed ) { if (!b) return 0; const int mod = _epg_object_set_htsmsg(b, &b->credits, credits, changed, EPG_CHANGED_CREDITS); @@ -1660,14 +1206,14 @@ int epg_broadcast_set_credits } int epg_broadcast_set_category -( epg_broadcast_t *b, const string_list_t *msg, uint32_t *changed ) +( epg_broadcast_t *b, const string_list_t *msg, epg_changes_t *changed ) { if (!b) return 0; return _epg_object_set_string_list(b, &b->category, msg, changed, EPG_CHANGED_CATEGORY); } int epg_broadcast_set_keyword -( epg_broadcast_t *b, const string_list_t *msg, uint32_t *changed ) +( epg_broadcast_t *b, const string_list_t *msg, epg_changes_t *changed ) { if (!b) return 0; const int mod = _epg_object_set_string_list(b, &b->keyword, msg, changed, EPG_CHANGED_KEYWORD); @@ -1688,6 +1234,133 @@ int epg_broadcast_set_keyword return mod; } +int epg_broadcast_set_image + ( epg_broadcast_t *b, const char *image, epg_changes_t *changed ) +{ + int save; + if (!b) return 0; + save = _epg_object_set_str(b, &b->image, image, + changed, EPG_CHANGED_IMAGE); + if (save) + imagecache_get_id(image); + return save; +} + +int epg_broadcast_set_epnumber + ( epg_broadcast_t *b, uint16_t number, epg_changes_t *changed ) +{ + if (!b) return 0; + return _epg_object_set_u16(b, &b->epnum.e_num, number, + changed, EPG_CHANGED_EPNUM_NUM); +} + +int epg_broadcast_set_eppart + ( epg_broadcast_t *b, uint16_t part, uint16_t count, + epg_changes_t *changed ) +{ + int save = 0; + if (!b) return 0; + save |= _epg_object_set_u16(b, &b->epnum.p_num, part, + changed, EPG_CHANGED_EPPAR_NUM); + save |= _epg_object_set_u16(b, &b->epnum.p_cnt, count, + changed, EPG_CHANGED_EPPAR_CNT); + return save; +} + +int epg_broadcast_set_epnum + ( epg_broadcast_t *b, epg_episode_num_t *num, epg_changes_t *changed ) +{ + int save = 0; + static epg_episode_num_t _zero = { 0 }; + if (!b) + return 0; + if (!num) + num = &_zero; + if (num->s_num) + save |= _epg_object_set_u16(b, &b->epnum.s_num, + num->s_num, changed, EPG_CHANGED_EPSER_NUM); + if (num->s_cnt) + save |= _epg_object_set_u16(b, &b->epnum.s_cnt, + num->s_cnt, changed, EPG_CHANGED_EPSER_CNT); + if (num->e_num) + save |= _epg_object_set_u16(b, &b->epnum.e_num, + num->e_num, changed, EPG_CHANGED_EPNUM_NUM); + if (num->e_cnt) + save |= _epg_object_set_u16(b, &b->epnum.e_cnt, + num->e_cnt, changed, EPG_CHANGED_EPNUM_CNT); + if (num->p_num) + save |= _epg_object_set_u16(b, &b->epnum.p_num, + num->p_num, changed, EPG_CHANGED_EPPAR_NUM); + if (num->p_cnt) + save |= _epg_object_set_u16(b, &b->epnum.p_cnt, + num->p_cnt, changed, EPG_CHANGED_EPPAR_CNT); + if (num->text) + save |= _epg_object_set_str(b, &b->epnum.text, + num->text, changed, EPG_CHANGED_EPTEXT); + return save; +} + +int epg_broadcast_set_genre + ( epg_broadcast_t *b, epg_genre_list_t *genre, epg_changes_t *changed ) +{ + int save = 0; + epg_genre_t *g1, *g2; + + if (!b) return 0; + + if (changed) *changed |= EPG_CHANGED_GENRE; + + g1 = LIST_FIRST(&b->genre); + + /* Remove old */ + while (g1) { + g2 = LIST_NEXT(g1, link); + if (!epg_genre_list_contains(genre, g1, 0)) { + LIST_REMOVE(g1, link); + free(g1); + save = 1; + } + g1 = g2; + } + + /* Insert all entries */ + if (genre) { + LIST_FOREACH(g1, genre, link) + save |= epg_genre_list_add(&b->genre, g1); + } + + return save; +} + +int epg_broadcast_set_copyright_year + ( epg_broadcast_t *b, uint16_t year, epg_changes_t *changed ) +{ + if (!b) return 0; + return _epg_object_set_u16(b, &b->copyright_year, year, + changed, EPG_CHANGED_COPYRIGHT_YEAR); +} + +int epg_broadcast_set_age_rating + ( epg_broadcast_t *b, uint8_t age, epg_changes_t *changed ) +{ + if (!b) return 0; + return _epg_object_set_u8(b, &b->age_rating, age, + changed, EPG_CHANGED_AGE_RATING); +} + +int epg_broadcast_set_first_aired + ( epg_broadcast_t *b, time_t aired, epg_changes_t *changed ) +{ + if (!b) return 0; + if (changed) *changed |= EPG_CHANGED_FIRST_AIRED; + if (b->first_aired != aired) { + b->first_aired = aired; + _epg_object_set_updated(b); + return 1; + } + return 0; +} + epg_broadcast_t *epg_broadcast_get_next ( epg_broadcast_t *broadcast ) { if ( !broadcast ) return NULL; @@ -1696,14 +1369,14 @@ epg_broadcast_t *epg_broadcast_get_next ( epg_broadcast_t *broadcast ) const char *epg_broadcast_get_title ( epg_broadcast_t *b, const char *lang ) { - if (!b || !b->episode) return NULL; - return epg_episode_get_title(b->episode, lang); + if (!b && !b->title) return NULL; + return lang_str_get(b->title, lang); } const char *epg_broadcast_get_subtitle ( epg_broadcast_t *b, const char *lang ) { - if (!b || !b->episode) return NULL; - return epg_episode_get_subtitle(b->episode, lang); + if (!b && !b->subtitle) return NULL; + return lang_str_get(b->subtitle, lang); } const char *epg_broadcast_get_summary ( epg_broadcast_t *b, const char *lang ) @@ -1730,16 +1403,38 @@ const char *epg_broadcast_get_description ( epg_broadcast_t *b, const char *lang return lang_str_get(b->description, lang); } +void epg_broadcast_get_epnum ( const epg_broadcast_t *b, epg_episode_num_t *num ) +{ + if (!b || !num) { + if (num) + memset(num, 0, sizeof(*num)); + return; + } + *num = b->epnum; +} + +size_t epg_broadcast_epnumber_format + ( epg_broadcast_t *b, char *buf, size_t len, + const char *pre, const char *sfmt, + const char *sep, const char *efmt, + const char *cfmt ) +{ + if (!b) return 0; + epg_episode_num_t num; + epg_broadcast_get_epnum(b, &num); + return epg_episode_num_format(&num, buf, len, pre, + sfmt, sep, efmt, cfmt); +} + htsmsg_t *epg_broadcast_serialize ( epg_broadcast_t *broadcast ) { - htsmsg_t *m; + htsmsg_t *m, *a; + epg_genre_t *eg; char ubuf[UUID_HEX_SIZE]; if (!broadcast) return NULL; - if (!broadcast->episode || !broadcast->episode->uri) return NULL; if (!(m = _epg_object_serialize((epg_object_t*)broadcast))) return NULL; htsmsg_add_s64(m, "start", broadcast->start); htsmsg_add_s64(m, "stop", broadcast->stop); - htsmsg_add_str(m, "episode", broadcast->episode->uri); if (broadcast->channel) htsmsg_add_str(m, "channel", channel_get_uuid(broadcast->channel, ubuf)); if (broadcast->dvb_eid) @@ -1748,6 +1443,8 @@ htsmsg_t *epg_broadcast_serialize ( epg_broadcast_t *broadcast ) htsmsg_add_u32(m, "is_widescreen", 1); if (broadcast->is_hd) htsmsg_add_u32(m, "is_hd", 1); + if (broadcast->is_bw) + htsmsg_add_u32(m, "is_bw", 1); if (broadcast->lines) htsmsg_add_u32(m, "lines", broadcast->lines); if (broadcast->aspect) @@ -1762,12 +1459,32 @@ htsmsg_t *epg_broadcast_serialize ( epg_broadcast_t *broadcast ) htsmsg_add_u32(m, "is_new", 1); if (broadcast->is_repeat) htsmsg_add_u32(m, "is_repeat", 1); + if (broadcast->star_rating) + htsmsg_add_u32(m, "star_rating", broadcast->star_rating); + if (broadcast->age_rating) + htsmsg_add_u32(m, "age_rating", broadcast->age_rating); + if (broadcast->image) + htsmsg_add_str(m, "image", broadcast->image); + if (broadcast->title) + lang_str_serialize(broadcast->summary, m, "title"); + if (broadcast->subtitle) + lang_str_serialize(broadcast->summary, m, "subtitle"); if (broadcast->summary) lang_str_serialize(broadcast->summary, m, "summary"); if (broadcast->description) lang_str_serialize(broadcast->description, m, "description"); + htsmsg_add_msg(m, "epnum", epg_episode_epnum_serialize(&broadcast->epnum)); + LIST_FOREACH(eg, &broadcast->genre, link) { + if (!a) a = htsmsg_create_list(); + htsmsg_add_u32(a, NULL, eg->code); + } + if (a) htsmsg_add_msg(m, "genre", a); + if (broadcast->copyright_year) + htsmsg_add_u32(m, "copyright_year", broadcast->copyright_year); + if (broadcast->first_aired) + htsmsg_add_s64(m, "first_aired", broadcast->first_aired); if (broadcast->credits) - htsmsg_add_msg(m, "credits", htsmsg_copy(broadcast->credits)); + htsmsg_add_msg(m, "credits", htsmsg_copy(broadcast->credits)); /* No need to serialize credits_cached since it is rebuilt from credits. */ if (broadcast->category) string_list_serialize(broadcast->category, m, "category"); @@ -1776,7 +1493,6 @@ htsmsg_t *epg_broadcast_serialize ( epg_broadcast_t *broadcast ) /* No need to serialize keyword_cached since it is rebuilt from keyword */ if (broadcast->serieslink_uri) htsmsg_add_str(m, "serieslink", broadcast->serieslink_uri); - return m; } @@ -1785,13 +1501,15 @@ epg_broadcast_t *epg_broadcast_deserialize { channel_t *ch = NULL; epg_broadcast_t *ebc, **skel = _epg_broadcast_skel(); - epg_episode_t *ee; lang_str_t *ls; htsmsg_t *hm; + htsmsg_field_t *f; string_list_t *sl; const char *str; - uint32_t eid, u32, changes = 0; - int64_t start, stop; + uint32_t eid, u32; + epg_changes_t changes = 0; + int64_t start, stop, s64; + epg_episode_num_t num; if (htsmsg_get_s64(m, "start", &start)) return NULL; if (htsmsg_get_s64(m, "stop", &stop)) return NULL; @@ -1802,9 +1520,6 @@ epg_broadcast_t *epg_broadcast_deserialize _epg_object_deserialize(m, (epg_object_t*)*skel); - if (!(ee = epg_episode_find_by_uri(str, (*skel)->grabber, 0, NULL, NULL))) - return NULL; - /* Set properties */ (*skel)->start = start; (*skel)->stop = stop; @@ -1825,6 +1540,8 @@ epg_broadcast_t *epg_broadcast_deserialize *save |= epg_broadcast_set_is_widescreen(ebc, u32, &changes); if (!htsmsg_get_u32(m, "is_hd", &u32)) *save |= epg_broadcast_set_is_hd(ebc, u32, &changes); + if (!htsmsg_get_u32(m, "is_bw", &u32)) + *save |= epg_broadcast_set_is_bw(ebc, u32, &changes); if (!htsmsg_get_u32(m, "lines", &u32)) *save |= epg_broadcast_set_lines(ebc, u32, &changes); if (!htsmsg_get_u32(m, "aspect", &u32)) @@ -1839,38 +1556,69 @@ epg_broadcast_t *epg_broadcast_deserialize *save |= epg_broadcast_set_is_new(ebc, u32, &changes); if (!htsmsg_get_u32(m, "is_repeat", &u32)) *save |= epg_broadcast_set_is_repeat(ebc, u32, &changes); + if (!htsmsg_get_u32(m, "star_rating", &u32)) + *save |= epg_broadcast_set_star_rating(ebc, u32, &changes); + if (!htsmsg_get_u32(m, "age_rating", &u32)) + *save |= epg_broadcast_set_age_rating(ebc, u32, &changes); + + if ((str = htsmsg_get_str(m, "image"))) + *save |= epg_broadcast_set_image(ebc, str, &changes); + if ((hm = htsmsg_get_list(m, "genre"))) { + epg_genre_list_t *egl = calloc(1, sizeof(epg_genre_list_t)); + HTSMSG_FOREACH(f, hm) { + epg_genre_t genre; + genre.code = (uint8_t)f->hmf_s64; + epg_genre_list_add(egl, &genre); + } + *save |= epg_broadcast_set_genre(ebc, egl, &changes); + epg_genre_list_destroy(egl); + } + + if ((ls = lang_str_deserialize(m, "title"))) { + *save |= epg_broadcast_set_title(ebc, ls, &changes); + lang_str_destroy(ls); + } + if ((ls = lang_str_deserialize(m, "subtitle"))) { + *save |= epg_broadcast_set_subtitle(ebc, ls, &changes); + lang_str_destroy(ls); + } if ((ls = lang_str_deserialize(m, "summary"))) { *save |= epg_broadcast_set_summary(ebc, ls, &changes); lang_str_destroy(ls); } - if ((ls = lang_str_deserialize(m, "description"))) { *save |= epg_broadcast_set_description(ebc, ls, &changes); lang_str_destroy(ls); } - if ((hm = htsmsg_get_map(m, "credits"))) { - *save |= epg_broadcast_set_credits(ebc, hm, &changes); + if ((hm = htsmsg_get_map(m, "epnum"))) { + epg_episode_epnum_deserialize(hm, &num); + *save |= epg_broadcast_set_epnum(ebc, &num, &changes); + if (num.text) free(num.text); } + if (!htsmsg_get_u32(m, "copyright_year", &u32)) + *save |= epg_broadcast_set_copyright_year(ebc, u32, &changes); + if (!htsmsg_get_s64(m, "first_aired", &s64)) + *save |= epg_broadcast_set_first_aired(ebc, (time_t)s64, &changes); + + if ((hm = htsmsg_get_map(m, "credits"))) + *save |= epg_broadcast_set_credits(ebc, hm, &changes); + if ((sl = string_list_deserialize(m, "keyword"))) { - *save |= epg_broadcast_set_keyword(ebc, sl, &changes); - string_list_destroy(sl); + *save |= epg_broadcast_set_keyword(ebc, sl, &changes); + string_list_destroy(sl); } - if ((sl = string_list_deserialize(m, "category"))) { - *save |= epg_broadcast_set_category(ebc, sl, &changes); - string_list_destroy(sl); + *save |= epg_broadcast_set_category(ebc, sl, &changes); + string_list_destroy(sl); } /* Series link */ if ((str = htsmsg_get_str(m, "serieslink"))) *save |= epg_broadcast_set_serieslink_uri(ebc, str, &changes); - /* Set the episode */ - *save |= epg_broadcast_set_episode(ebc, ee, &changes); - *save |= epg_broadcast_change_finish(ebc, changes, 0); return ebc; @@ -2286,7 +2034,6 @@ static void _eq_add ( epg_query_t *eq, epg_broadcast_t *e ) { const char *s, *lang = eq->lang; - epg_episode_t *ep; int fulltext = eq->stitle && eq->fulltext; /* Filtering */ @@ -2298,11 +2045,10 @@ _eq_add ( epg_query_t *eq, epg_broadcast_t *e ) int64_t duration = (int64_t)e->stop - (int64_t)e->start; if (_eq_comp_num(&eq->duration, duration)) return; } - ep = e->episode; if (eq->stars.comp != EC_NO) - if (_eq_comp_num(&eq->stars, ep->star_rating)) return; + if (_eq_comp_num(&eq->stars, e->star_rating)) return; if (eq->age.comp != EC_NO) - if (_eq_comp_num(&eq->age, ep->age_rating)) return; + if (_eq_comp_num(&eq->age, e->age_rating)) return; if (eq->channel_num.comp != EC_NO) if (_eq_comp_num(&eq->channel_num, channel_get_number(e->channel))) return; if (eq->channel_name.comp != EC_NO) @@ -2335,7 +2081,7 @@ _eq_add ( epg_query_t *eq, epg_broadcast_t *e ) for (i = 0; i < eq->genre_count; i++) { genre.code = eq->genre[i]; if (genre.code == 0) continue; - if (epg_genre_list_contains(&e->episode->genre, &genre, 1)) r++; + if (epg_genre_list_contains(&e->genre, &genre, 1)) r++; } if (!r) return; } @@ -2344,9 +2090,9 @@ _eq_add ( epg_query_t *eq, epg_broadcast_t *e ) return; } if (fulltext) { - if ((s = epg_episode_get_title(ep, lang)) == NULL || + if ((s = epg_broadcast_get_title(e, lang)) == NULL || regex_match(&eq->stitle_re, s)) { - if ((s = epg_episode_get_subtitle(ep, lang)) == NULL || + if ((s = epg_broadcast_get_subtitle(e, lang)) == NULL || regex_match(&eq->stitle_re, s)) { if ((s = epg_broadcast_get_summary(e, lang)) == NULL || regex_match(&eq->stitle_re, s)) { @@ -2365,12 +2111,12 @@ _eq_add ( epg_query_t *eq, epg_broadcast_t *e ) } } if (eq->title.comp != EC_NO || (eq->stitle && !fulltext)) { - if ((s = epg_episode_get_title(ep, lang)) == NULL) return; + if ((s = epg_broadcast_get_title(e, lang)) == NULL) return; if (eq->stitle && !fulltext && regex_match(&eq->stitle_re, s)) return; if (eq->title.comp != EC_NO && _eq_comp_str(&eq->title, s)) return; } if (eq->subtitle.comp != EC_NO) { - if ((s = epg_episode_get_subtitle(ep, lang)) == NULL) return; + if ((s = epg_broadcast_get_subtitle(e, lang)) == NULL) return; if (_eq_comp_str(&eq->subtitle, s)) return; } if (eq->summary.comp != EC_NO) { @@ -2396,10 +2142,8 @@ static void _eq_add_channel ( epg_query_t *eq, channel_t *ch ) { epg_broadcast_t *ebc; - RB_FOREACH(ebc, &ch->ch_epg_schedule, sched_link) { - if (ebc->episode) - _eq_add(eq, ebc); - } + RB_FOREACH(ebc, &ch->ch_epg_schedule, sched_link) + _eq_add(eq, ebc); } static int @@ -2561,37 +2305,37 @@ static int _epg_sort_channel_num_ascending ( const void *a, const void *b, void static int _epg_sort_channel_num_descending ( const void *a, const void *b, void *eq ) { - int64_t v1 = channel_get_number((*(epg_broadcast_t**)a)->channel); - int64_t v2 = channel_get_number((*(epg_broadcast_t**)b)->channel); + const int64_t v1 = channel_get_number((*(epg_broadcast_t**)a)->channel); + const int64_t v2 = channel_get_number((*(epg_broadcast_t**)b)->channel); return v2 - v1; } static int _epg_sort_stars_ascending ( const void *a, const void *b, void *eq ) { - return (*(epg_broadcast_t**)a)->episode->star_rating - (*(epg_broadcast_t**)b)->episode->star_rating; + return (*(epg_broadcast_t**)a)->star_rating - (*(epg_broadcast_t**)b)->star_rating; } static int _epg_sort_stars_descending ( const void *a, const void *b, void *eq ) { - return (*(epg_broadcast_t**)b)->episode->star_rating - (*(epg_broadcast_t**)a)->episode->star_rating; + return (*(epg_broadcast_t**)b)->star_rating - (*(epg_broadcast_t**)a)->star_rating; } static int _epg_sort_age_ascending ( const void *a, const void *b, void *eq ) { - return (*(epg_broadcast_t**)a)->episode->age_rating - (*(epg_broadcast_t**)b)->episode->age_rating; + return (*(epg_broadcast_t**)a)->age_rating - (*(epg_broadcast_t**)b)->age_rating; } static int _epg_sort_age_descending ( const void *a, const void *b, void *eq ) { - return (*(epg_broadcast_t**)b)->episode->age_rating - (*(epg_broadcast_t**)a)->episode->age_rating; + return (*(epg_broadcast_t**)b)->age_rating - (*(epg_broadcast_t**)a)->age_rating; } -static uint64_t _epg_sort_genre_hash( epg_episode_t *ep ) +static uint64_t _epg_sort_genre_hash( epg_broadcast_t *b ) { uint64_t h = 0, t; epg_genre_t *g; - LIST_FOREACH(g, &ep->genre, link) { + LIST_FOREACH(g, &b->genre, link) { t = h >> 28; h <<= 8; h += (uint64_t)g->code + t; @@ -2601,8 +2345,8 @@ static uint64_t _epg_sort_genre_hash( epg_episode_t *ep ) static int _epg_sort_genre_ascending ( const void *a, const void *b, void *eq ) { - uint64_t v1 = _epg_sort_genre_hash((*(epg_broadcast_t**)a)->episode); - uint64_t v2 = _epg_sort_genre_hash((*(epg_broadcast_t**)b)->episode); + const uint64_t v1 = _epg_sort_genre_hash(*(epg_broadcast_t**)a); + const uint64_t v2 = _epg_sort_genre_hash(*(epg_broadcast_t**)b); return v1 - v2; } @@ -2750,11 +2494,8 @@ int epg_config_deserialize( htsmsg_t *m ) void epg_skel_done(void) { - epg_object_t **skel; epg_broadcast_t **broad; - skel = _epg_episode_skel(); - free(*skel); *skel = NULL; broad = _epg_broadcast_skel(); free(*broad); *broad = NULL; } diff --git a/src/epg.h b/src/epg.h index 45c3eb8aa..294812cae 100644 --- a/src/epg.h +++ b/src/epg.h @@ -38,7 +38,6 @@ struct epggrab_module; */ typedef LIST_HEAD(,epg_object) epg_object_list_t; typedef RB_HEAD (,epg_object) epg_object_tree_t; -typedef LIST_HEAD(,epg_episode) epg_episode_list_t; typedef LIST_HEAD(,epg_broadcast) epg_broadcast_list_t; typedef RB_HEAD (,epg_broadcast) epg_broadcast_tree_t; typedef LIST_HEAD(,epg_genre) epg_genre_list_t; @@ -48,7 +47,6 @@ typedef LIST_HEAD(,epg_genre) epg_genre_list_t; */ typedef struct epg_genre epg_genre_t; typedef struct epg_object epg_object_t; -typedef struct epg_episode epg_episode_t; typedef struct epg_broadcast epg_broadcast_t; extern int epg_in_load; @@ -104,22 +102,48 @@ htsmsg_t *epg_genres_list_all ( int major_only, int major_prefix, const char *la typedef enum epg_object_type { EPG_UNDEF, - EPG_EPISODE, EPG_BROADCAST, } epg_object_type_t; #define EPG_TYPEMAX EPG_BROADCAST -/* Change flags - shared */ -#define EPG_CHANGED_CREATE (1<<0) -#define EPG_CHANGED_TITLE (1<<1) -#define EPG_CHANGED_SUBTITLE (1<<2) -#define EPG_CHANGED_SUMMARY (1<<3) -#define EPG_CHANGED_DESCRIPTION (1<<4) -#define EPG_CHANGED_IMAGE (1<<5) -#define EPG_CHANGED_CREDITS (1<<6) -#define EPG_CHANGED_CATEGORY (1<<7) -#define EPG_CHANGED_KEYWORD (1<<8) -#define EPG_CHANGED_SLAST 2 +/* Change type */ +typedef uint64_t epg_changes_t; + +/* Change flags */ +#define EPG_CHANGED_CREATE (1ULL<<0) +#define EPG_CHANGED_TITLE (1ULL<<1) +#define EPG_CHANGED_SUBTITLE (1ULL<<2) +#define EPG_CHANGED_SUMMARY (1ULL<<3) +#define EPG_CHANGED_DESCRIPTION (1ULL<<4) +#define EPG_CHANGED_IMAGE (1ULL<<5) +#define EPG_CHANGED_CREDITS (1ULL<<6) +#define EPG_CHANGED_CATEGORY (1ULL<<7) +#define EPG_CHANGED_KEYWORD (1ULL<<8) +#define EPG_CHANGED_DVB_EID (1ULL<<9) +#define EPG_CHANGED_IS_WIDESCREEN (1ULL<<10) +#define EPG_CHANGED_IS_HD (1ULL<<11) +#define EPG_CHANGED_LINES (1ULL<<12) +#define EPG_CHANGED_ASPECT (1ULL<<13) +#define EPG_CHANGED_DEAFSIGNED (1ULL<<14) +#define EPG_CHANGED_SUBTITLED (1ULL<<15) +#define EPG_CHANGED_AUDIO_DESC (1ULL<<16) +#define EPG_CHANGED_IS_NEW (1ULL<<17) +#define EPG_CHANGED_IS_REPEAT (1ULL<<18) +#define EPG_CHANGED_SERIESLINK (1ULL<<19) +#define EPG_CHANGED_EPISODE (1ULL<<20) +#define EPG_CHANGED_GENRE (1ULL<<21) +#define EPG_CHANGED_EPNUM_NUM (1ULL<<22) +#define EPG_CHANGED_EPNUM_CNT (1ULL<<23) +#define EPG_CHANGED_EPPAR_NUM (1ULL<<24) +#define EPG_CHANGED_EPPAR_CNT (1ULL<<25) +#define EPG_CHANGED_EPSER_NUM (1ULL<<26) +#define EPG_CHANGED_EPSER_CNT (1ULL<<27) +#define EPG_CHANGED_EPTEXT (1ULL<<28) +#define EPG_CHANGED_IS_BW (1ULL<<29) +#define EPG_CHANGED_STAR_RATING (1ULL<<30) +#define EPG_CHANGED_AGE_RATING (1ULL<<31) +#define EPG_CHANGED_FIRST_AIRED (1ULL<<32) +#define EPG_CHANGED_COPYRIGHT_YEAR (1ULL<<33) typedef struct epg_object_ops { void (*getref) ( void *o ); ///< Get a reference @@ -138,7 +162,6 @@ struct epg_object epg_object_type_t type; ///< Specific object type uint32_t id; ///< Internal ID - char *uri; ///< Unique ID (from grabber) time_t updated; ///< Last time object was changed uint8_t _updated; ///< Flag to indicate updated @@ -157,27 +180,9 @@ htsmsg_t *epg_object_serialize ( epg_object_t *eo ); epg_object_t *epg_object_deserialize ( htsmsg_t *msg, int create, int *save ); /* ************************************************************************ - * Episode + * Episode numbering * ***********************************************************************/ -/* Change flags */ -#define EPG_CHANGED_GENRE (1<<(EPG_CHANGED_SLAST+1)) -#define EPG_CHANGED_EPNUM_NUM (1<<(EPG_CHANGED_SLAST+2)) -#define EPG_CHANGED_EPNUM_CNT (1<<(EPG_CHANGED_SLAST+3)) -#define EPG_CHANGED_EPPAR_NUM (1<<(EPG_CHANGED_SLAST+4)) -#define EPG_CHANGED_EPPAR_CNT (1<<(EPG_CHANGED_SLAST+5)) -#define EPG_CHANGED_EPSER_NUM (1<<(EPG_CHANGED_SLAST+6)) -#define EPG_CHANGED_EPSER_CNT (1<<(EPG_CHANGED_SLAST+7)) -#define EPG_CHANGED_EPTEXT (1<<(EPG_CHANGED_SLAST+8)) -#define EPG_CHANGED_IS_BW (1<<(EPG_CHANGED_SLAST+9)) -#define EPG_CHANGED_STAR_RATING (1<<(EPG_CHANGED_SLAST+10)) -#define EPG_CHANGED_AGE_RATING (1<<(EPG_CHANGED_SLAST+11)) -#define EPG_CHANGED_FIRST_AIRED (1<<(EPG_CHANGED_SLAST+12)) -#define EPG_CHANGED_COPYRIGHT_YEAR (1<<(EPG_CHANGED_SLAST+13)) - -/* Episode numbering object - this is for some back-compat and also - * to allow episode information to be "collated" into easy to use object - */ typedef struct epg_episode_num { uint16_t s_num; ///< Series number @@ -189,102 +194,9 @@ typedef struct epg_episode_num char *text; ///< Arbitary text description of episode num } epg_episode_num_t; -/* Object */ -struct epg_episode -{ - epg_object_t; ///< Parent object - - lang_str_t *title; ///< Title - lang_str_t *subtitle; ///< Sub-title - lang_str_t *summary; ///< Summary - lang_str_t *description; ///< An extended description - char *image; ///< Episode image - epg_genre_list_t genre; ///< Episode genre(s) - epg_episode_num_t epnum; ///< Episode numbering - // Note: do not use epnum directly! use the accessor routine - - uint8_t is_bw; ///< Is black and white - uint8_t star_rating; ///< Star rating - uint8_t age_rating; ///< Age certificate - time_t first_aired; ///< Original airdate - uint16_t copyright_year; ///< xmltv DTD gives a tag "date" (separate to previously-shown/first aired). - ///< This is the date programme was "finished...probably the copyright date." - ///< We'll call it copyright_year since words like "complete" and "finished" - ///< sound too similar to dvr recorded functionality. We'll only store the - ///< year since we only get year not month and day. - LIST_ENTRY(epg_episode) blink; ///< Brand link - LIST_ENTRY(epg_episode) slink; ///< Season link - epg_broadcast_list_t broadcasts; ///< Broadcast list -}; - -/* Lookup */ -epg_episode_t *epg_episode_find_by_uri - ( const char *uri, struct epggrab_module *src, int create, int *save, uint32_t *changes ); -epg_episode_t *epg_episode_find_by_id ( uint32_t id ); -epg_episode_t *epg_episode_find_by_broadcast - ( epg_broadcast_t *b, struct epggrab_module *src, int create, int *save, uint32_t *changes ); - -/* Post-modify */ -int epg_episode_change_finish( epg_episode_t *s, uint32_t changed, int merge ) - __attribute__((warn_unused_result)); - -/* Accessors */ -const char *epg_episode_get_title - ( const epg_episode_t *e, const char *lang ); -const char *epg_episode_get_subtitle - ( const epg_episode_t *e, const char *lang ); -const char *epg_episode_get_summary - ( const epg_episode_t *e, const char *lang ); -const char *epg_episode_get_description - ( const epg_episode_t *e, const char *lang ); - -/* Mutators */ -int epg_episode_set_title - ( epg_episode_t *e, const lang_str_t *title, uint32_t *changed ) - __attribute__((warn_unused_result)); -int epg_episode_set_subtitle - ( epg_episode_t *e, const lang_str_t *subtitle, uint32_t *changed ) - __attribute__((warn_unused_result)); -int epg_episode_set_summary - ( epg_episode_t *e, const lang_str_t *summary, uint32_t *changed ) - __attribute__((warn_unused_result)); -int epg_episode_set_description - ( epg_episode_t *e, const lang_str_t *description, uint32_t *changed ) - __attribute__((warn_unused_result)); -int epg_episode_set_number - ( epg_episode_t *e, uint16_t number, uint32_t *changed ) - __attribute__((warn_unused_result)); -int epg_episode_set_part - ( epg_episode_t *e, uint16_t number, uint16_t count, uint32_t *changed ) - __attribute__((warn_unused_result)); -int epg_episode_set_epnum - ( epg_episode_t *e, epg_episode_num_t *num, uint32_t *changed ) - __attribute__((warn_unused_result)); -int epg_episode_set_genre - ( epg_episode_t *e, epg_genre_list_t *g, uint32_t *changed ) - __attribute__((warn_unused_result)); -int epg_episode_set_image - ( epg_episode_t *e, const char *i, uint32_t *changed ) - __attribute__((warn_unused_result)); -int epg_episode_set_is_bw - ( epg_episode_t *e, uint8_t bw, uint32_t *changed ) - __attribute__((warn_unused_result)); -int epg_episode_set_first_aired - ( epg_episode_t *e, time_t aired, uint32_t *changed ) - __attribute__((warn_unused_result)); -int epg_episode_set_star_rating - ( epg_episode_t *e, uint8_t stars, uint32_t *changed ) - __attribute__((warn_unused_result)); -int epg_episode_set_copyright_year - ( epg_episode_t *e, uint16_t stars, uint32_t *changed ) - __attribute__((warn_unused_result)); -int epg_episode_set_age_rating - ( epg_episode_t *e, uint8_t age, uint32_t *changed ) - __attribute__((warn_unused_result)); +htsmsg_t *epg_episode_epnum_serialize( epg_episode_num_t *num ); +void epg_episode_epnum_deserialize( htsmsg_t *m, epg_episode_num_t *num ); -// Note: this does NOT strdup the text field -void epg_episode_get_epnum - ( const epg_episode_t *e, epg_episode_num_t *epnum ); /* EpNum format helper */ // output string will be: // if (episode_num) @@ -295,64 +207,40 @@ void epg_episode_get_epnum // ret += sprintf(efmt, episode_num) // if (episode_cnt) ret += sprintf(cfmt, episode_cnt) // and will return num chars written -size_t epg_episode_epnum_format +size_t epg_episode_num_format ( epg_episode_num_t *epnum, char *buf, size_t len, const char *pre, const char *sfmt, const char *sep, const char *efmt, const char *cfmt ); -size_t epg_episode_number_format - ( epg_episode_t *e, char *buf, size_t len, - const char *pre, const char *sfmt, - const char *sep, const char *efmt, - const char *cfmt ); int epg_episode_number_cmp ( const epg_episode_num_t *a, const epg_episode_num_t *b ); int epg_episode_number_cmpfull ( const epg_episode_num_t *a, const epg_episode_num_t *b ); -htsmsg_t *epg_episode_epnum_serialize( epg_episode_num_t *num ); -void epg_episode_epnum_deserialize( htsmsg_t *m, epg_episode_num_t *num ); - -/* Matching */ -int epg_episode_fuzzy_match - ( epg_episode_t *ee, const char *uri, const char *title, - const char *summary, const char *description ); - -/* Serialization */ -htsmsg_t *epg_episode_serialize ( epg_episode_t *b ); -epg_episode_t *epg_episode_deserialize ( htsmsg_t *m, int create, int *save ); - /* ************************************************************************ * Broadcast - specific airing (channel & time) of an episode * ***********************************************************************/ -#define EPG_CHANGED_DVB_EID (1<<(EPG_CHANGED_SLAST+1)) -#define EPG_CHANGED_IS_WIDESCREEN (1<<(EPG_CHANGED_SLAST+2)) -#define EPG_CHANGED_IS_HD (1<<(EPG_CHANGED_SLAST+3)) -#define EPG_CHANGED_LINES (1<<(EPG_CHANGED_SLAST+4)) -#define EPG_CHANGED_ASPECT (1<<(EPG_CHANGED_SLAST+5)) -#define EPG_CHANGED_DEAFSIGNED (1<<(EPG_CHANGED_SLAST+6)) -#define EPG_CHANGED_SUBTITLED (1<<(EPG_CHANGED_SLAST+7)) -#define EPG_CHANGED_AUDIO_DESC (1<<(EPG_CHANGED_SLAST+8)) -#define EPG_CHANGED_IS_NEW (1<<(EPG_CHANGED_SLAST+9)) -#define EPG_CHANGED_IS_REPEAT (1<<(EPG_CHANGED_SLAST+10)) -#define EPG_CHANGED_EPISODE (1<<(EPG_CHANGED_SLAST+11)) -#define EPG_CHANGED_SERIESLINK (1<<(EPG_CHANGED_SLAST+12)) - /* Object */ struct epg_broadcast { epg_object_t; ///< Parent object + + struct channel *channel; ///< Channel being broadcast on + RB_ENTRY(epg_broadcast) sched_link; ///< Schedule link + LIST_HEAD(, dvr_entry) dvr_entries; ///< Associated DVR entries + /* */ uint16_t dvb_eid; ///< DVB Event ID time_t start; ///< Start time time_t stop; ///< End time /* Some quality info */ - uint8_t is_widescreen; ///< Is widescreen - uint8_t is_hd; ///< Is HD uint16_t lines; ///< Lines in image (quality) uint16_t aspect; ///< Aspect ratio (*100) + uint8_t is_widescreen; ///< Is widescreen + uint8_t is_hd; ///< Is HD + uint8_t is_bw; ///< Is black and white /* Some accessibility support */ uint8_t is_deafsigned; ///< In screen signing @@ -360,14 +248,23 @@ struct epg_broadcast uint8_t is_audio_desc; ///< Audio description /* Misc flags */ + uint8_t star_rating; ///< Star rating + uint8_t age_rating; ///< Age certificate uint8_t is_new; ///< New series / file premiere uint8_t is_repeat; ///< Repeat screening uint8_t running; ///< EPG running flag uint8_t update_running; ///< new EPG running flag /* Broadcast level text */ + lang_str_t *title; ///< Title + lang_str_t *subtitle; ///< Sub-title lang_str_t *summary; ///< Summary lang_str_t *description; ///< Description + + char *image; ///< Episode image + epg_genre_list_t genre; ///< Episode genre(s) + epg_episode_num_t epnum; ///< Episode numbering + htsmsg_t *credits; ///< Cast/Credits map of name -> role type (actor, presenter, director, etc). lang_str_t *credits_cached; ///< Comma separated cast (for regex searching in GUI/autorec). Kept in sync with cast_map string_list_t *category; ///< Extra categories (typically from xmltv) such as "Western" or "Sumo Wrestling". @@ -375,26 +272,28 @@ struct epg_broadcast ///< Used with drop-down lists in the GUI. string_list_t *keyword; ///< Extra keywords (typically from xmltv) such as "Wild West" or "Unicorn". lang_str_t *keyword_cached; ///< Cached CSV version for regex searches. - RB_ENTRY(epg_broadcast) sched_link; ///< Schedule link - LIST_ENTRY(epg_broadcast) ep_link; ///< Episode link - epg_episode_t *episode; ///< Episode shown - LIST_ENTRY(epg_broadcast) sl_link; ///< SeriesLink link char *serieslink_uri; ///< SeriesLink URI - struct channel *channel; ///< Channel being broadcast on + char *episode_uri; ///< Episode URI - /* DVR */ - LIST_HEAD(, dvr_entry) dvr_entries; ///< Associated DVR entries + // Note: do not use epnum directly! use the accessor routine + + time_t first_aired; ///< Original airdate + uint16_t copyright_year; ///< xmltv DTD gives a tag "date" (separate to previously-shown/first aired). + ///< This is the date programme was "finished...probably the copyright date." + ///< We'll call it copyright_year since words like "complete" and "finished" + ///< sound too similar to dvr recorded functionality. We'll only store the + ///< year since we only get year not month and day. }; /* Lookup */ epg_broadcast_t *epg_broadcast_find_by_time ( struct channel *ch, struct epggrab_module *src, - time_t start, time_t stop, int create, int *save, uint32_t *changes ); + time_t start, time_t stop, int create, int *save, epg_changes_t *changes ); epg_broadcast_t *epg_broadcast_find_by_eid ( struct channel *ch, uint16_t eid ); epg_broadcast_t *epg_broadcast_find_by_id ( uint32_t id ); /* Post-modify */ -int epg_broadcast_change_finish( epg_broadcast_t *b, uint32_t changed, int merge ) +int epg_broadcast_change_finish( epg_broadcast_t *b, epg_changes_t changed, int merge ) __attribute__((warn_unused_result)); /* Special */ @@ -403,58 +302,94 @@ epg_broadcast_t *epg_broadcast_clone /* Mutators */ int epg_broadcast_set_dvb_eid - ( epg_broadcast_t *b, uint16_t dvb_eid, uint32_t *changed ) + ( epg_broadcast_t *b, uint16_t dvb_eid, epg_changes_t *changed ) __attribute__((warn_unused_result)); int epg_broadcast_set_running ( epg_broadcast_t *b, epg_running_t running ) __attribute__((warn_unused_result)); -int epg_broadcast_set_episode - ( epg_broadcast_t *b, epg_episode_t *e, uint32_t *changed ) - __attribute__((warn_unused_result)); int epg_broadcast_set_is_widescreen - ( epg_broadcast_t *b, uint8_t ws, uint32_t *changed ) + ( epg_broadcast_t *b, uint8_t ws, epg_changes_t *changed ) __attribute__((warn_unused_result)); int epg_broadcast_set_is_hd - ( epg_broadcast_t *b, uint8_t hd, uint32_t *changed ) + ( epg_broadcast_t *b, uint8_t hd, epg_changes_t *changed ) __attribute__((warn_unused_result)); int epg_broadcast_set_lines - ( epg_broadcast_t *b, uint16_t lines, uint32_t *changed ) + ( epg_broadcast_t *b, uint16_t lines, epg_changes_t *changed ) __attribute__((warn_unused_result)); int epg_broadcast_set_aspect - ( epg_broadcast_t *b, uint16_t aspect, uint32_t *changed ) + ( epg_broadcast_t *b, uint16_t aspect, epg_changes_t *changed ) __attribute__((warn_unused_result)); int epg_broadcast_set_is_deafsigned - ( epg_broadcast_t *b, uint8_t ds, uint32_t *changed ) + ( epg_broadcast_t *b, uint8_t ds, epg_changes_t *changed ) __attribute__((warn_unused_result)); int epg_broadcast_set_is_subtitled - ( epg_broadcast_t *b, uint8_t st, uint32_t *changed ) + ( epg_broadcast_t *b, uint8_t st, epg_changes_t *changed ) __attribute__((warn_unused_result)); int epg_broadcast_set_is_audio_desc - ( epg_broadcast_t *b, uint8_t ad, uint32_t *changed ) + ( epg_broadcast_t *b, uint8_t ad, epg_changes_t *changed ) __attribute__((warn_unused_result)); int epg_broadcast_set_is_new - ( epg_broadcast_t *b, uint8_t n, uint32_t *changed ) + ( epg_broadcast_t *b, uint8_t n, epg_changes_t *changed ) __attribute__((warn_unused_result)); int epg_broadcast_set_is_repeat - ( epg_broadcast_t *b, uint8_t r, uint32_t *changed ) + ( epg_broadcast_t *b, uint8_t r, epg_changes_t *changed ) + __attribute__((warn_unused_result)); +int epg_broadcast_set_title + ( epg_broadcast_t *b, const lang_str_t *str, epg_changes_t *changed ) + __attribute__((warn_unused_result)); +int epg_broadcast_set_subtitle + ( epg_broadcast_t *b, const lang_str_t *str, epg_changes_t *changed ) __attribute__((warn_unused_result)); int epg_broadcast_set_summary - ( epg_broadcast_t *b, const lang_str_t *str, uint32_t *changed ) + ( epg_broadcast_t *b, const lang_str_t *str, epg_changes_t *changed ) __attribute__((warn_unused_result)); int epg_broadcast_set_description - ( epg_broadcast_t *b, const lang_str_t *str, uint32_t *changed ) + ( epg_broadcast_t *b, const lang_str_t *str, epg_changes_t *changed ) __attribute__((warn_unused_result)); int epg_broadcast_set_credits -( epg_broadcast_t *b, const htsmsg_t *msg, uint32_t *changed ) +( epg_broadcast_t *b, const htsmsg_t *msg, epg_changes_t *changed ) __attribute__((warn_unused_result)); int epg_broadcast_set_category -( epg_broadcast_t *b, const string_list_t *msg, uint32_t *changed ) +( epg_broadcast_t *b, const string_list_t *msg, epg_changes_t *changed ) __attribute__((warn_unused_result)); int epg_broadcast_set_keyword -( epg_broadcast_t *b, const string_list_t *msg, uint32_t *changed ) +( epg_broadcast_t *b, const string_list_t *msg, epg_changes_t *changed ) __attribute__((warn_unused_result)); int epg_broadcast_set_serieslink_uri - ( epg_broadcast_t *b, const char *uri, uint32_t *changed ) + ( epg_broadcast_t *b, const char *uri, epg_changes_t *changed ) + __attribute__((warn_unused_result)); +int epg_broadcast_set_episode_uri + ( epg_broadcast_t *b, const char *uri, epg_changes_t *changed ) + __attribute__((warn_unused_result)); +int epg_broadcast_set_epnumber + ( epg_broadcast_t *b, uint16_t number, epg_changes_t *changed ) + __attribute__((warn_unused_result)); +int epg_broadcast_set_eppart + ( epg_broadcast_t *b, uint16_t number, uint16_t count, epg_changes_t *changed ) + __attribute__((warn_unused_result)); +int epg_broadcast_set_epnum + ( epg_broadcast_t *b, epg_episode_num_t *num, epg_changes_t *changed ) + __attribute__((warn_unused_result)); +int epg_broadcast_set_genre + ( epg_broadcast_t *b, epg_genre_list_t *g, epg_changes_t *changed ) + __attribute__((warn_unused_result)); +int epg_broadcast_set_image + ( epg_broadcast_t *b, const char *i, epg_changes_t *changed ) + __attribute__((warn_unused_result)); +int epg_broadcast_set_is_bw + ( epg_broadcast_t *b, uint8_t bw, epg_changes_t *changed ) + __attribute__((warn_unused_result)); +int epg_broadcast_set_first_aired + ( epg_broadcast_t *b, time_t aired, epg_changes_t *changed ) + __attribute__((warn_unused_result)); +int epg_broadcast_set_star_rating + ( epg_broadcast_t *b, uint8_t stars, epg_changes_t *changed ) + __attribute__((warn_unused_result)); +int epg_broadcast_set_copyright_year + ( epg_broadcast_t *b, uint16_t stars, epg_changes_t *changed ) + __attribute__((warn_unused_result)); +int epg_broadcast_set_age_rating + ( epg_broadcast_t *b, uint8_t age, epg_changes_t *changed ) __attribute__((warn_unused_result)); /* Accessors */ @@ -473,6 +408,22 @@ const char *epg_broadcast_get_credits_cached const char *epg_broadcast_get_keyword_cached ( epg_broadcast_t *b, const char *lang ); +/* Episode number heplers */ +// Note: this does NOT strdup the text field +void epg_broadcast_get_epnum + ( const epg_broadcast_t *b, epg_episode_num_t *epnum ); +size_t epg_broadcast_epnumber_format + ( epg_broadcast_t *b, char *buf, size_t len, + const char *pre, const char *sfmt, + const char *sep, const char *efmt, + const char *cfmt ); + +static inline int epg_episode_match(epg_broadcast_t *a, epg_broadcast_t *b) +{ + if (a == NULL || b == NULL) return 0; + return strcmp(a->episode_uri ?: "", b->episode_uri ?: "") == 0; +} + /* Serialization */ htsmsg_t *epg_broadcast_serialize ( epg_broadcast_t *b ); epg_broadcast_t *epg_broadcast_deserialize diff --git a/src/epgdb.c b/src/epgdb.c index 95fcd35b4..9f91d140b 100644 --- a/src/epgdb.c +++ b/src/epgdb.c @@ -36,7 +36,7 @@ #include "config.h" #include "memoryinfo.h" -#define EPG_DB_VERSION 2 +#define EPG_DB_VERSION 3 #define EPG_DB_ALLOC_STEP (1024*1024) extern epg_object_tree_t epg_episodes; @@ -46,66 +46,10 @@ extern epg_object_tree_t epg_episodes; * *************************************************************************/ /* - * Use for v1 databases - */ -#if DEPRECATED -static void _epgdb_v1_process ( htsmsg_t *c, epggrab_stats_t *stats ) -{ - channel_t *ch; - epg_episode_t *ee; - epg_broadcast_t *ebc; - uint32_t ch_id = 0; - uint32_t e_start = 0; - uint32_t e_stop = 0; - uint32_t u32; - const char *title, *desc, *str; - char *uri; - int save = 0; - - /* Check key info */ - if(htsmsg_get_u32(c, "ch_id", &ch_id)) return; - if((ch = channel_find_by_id(ch_id)) == NULL) return; - if(htsmsg_get_u32(c, "start", &e_start)) return; - if(htsmsg_get_u32(c, "stop", &e_stop)) return; - if(!(title = htsmsg_get_str(c, "title"))) return; - - /* Create broadcast */ - save = 0; - ebc = epg_broadcast_find_by_time(ch, e_start, e_stop, 0, 1, &save); - if (!ebc) return; - if (save) stats->broadcasts.total++; - - /* Create episode */ - save = 0; - desc = htsmsg_get_str(c, "desc"); - uri = md5sum(desc ?: title); - ee = epg_episode_find_by_uri(uri, 1, &save); - free(uri); - if (!ee) return; - if (save) stats->episodes.total++; - if (title) - save |= epg_episode_set_title(ee, title, NULL, NULL); - if (desc) - save |= epg_episode_set_summary(ee, desc, NULL, NULL); - if (!htsmsg_get_u32(c, "episode", &u32)) - save |= epg_episode_set_number(ee, u32, NULL); - if (!htsmsg_get_u32(c, "part", &u32)) - save |= epg_episode_set_part(ee, u32, 0, NULL); - if (!htsmsg_get_u32(c, "season", &u32)) - ee->epnum.s_num = u32; - if ((str = htsmsg_get_str(c, "epname"))) - ee->epnum.text = strdup(str); - - /* Set episode */ - save |= epg_broadcast_set_episode(ebc, ee, NULL); -} -#endif - -/* - * Process v2 data + * Process v3 data */ static void -_epgdb_v2_process( char **sect, htsmsg_t *m, epggrab_stats_t *stats ) +_epgdb_v3_process( char **sect, htsmsg_t *m, epggrab_stats_t *stats ) { int save = 0; const char *s; @@ -115,22 +59,6 @@ _epgdb_v2_process( char **sect, htsmsg_t *m, epggrab_stats_t *stats ) if (*sect) free(*sect); *sect = strdup(s); - /* Brand */ - } else if ( !strcmp(*sect, "brands") ) { - /* skip */ - - /* Season */ - } else if ( !strcmp(*sect, "seasons") ) { - /* skip */ - - /* Episode */ - } else if ( !strcmp(*sect, "episodes") ) { - if (epg_episode_deserialize(m, 1, &save)) stats->episodes.total++; - - /* Series link */ - } else if ( !strcmp(*sect, "serieslinks") ) { - /* skip */ - /* Broadcasts */ } else if ( !strcmp(*sect, "broadcasts") ) { if (epg_broadcast_deserialize(m, 1, &save)) stats->broadcasts.total++; @@ -150,32 +78,6 @@ _epgdb_v2_process( char **sect, htsmsg_t *m, epggrab_stats_t *stats ) * Memoryinfo */ -static void epg_memoryinfo_episodes_update(memoryinfo_t *my) -{ - epg_object_t *eo; - epg_episode_t *ee; - int64_t size = 0, count = 0; - - RB_FOREACH(eo, &epg_episodes, uri_link) { - ee = (epg_episode_t *)eo; - size += sizeof(*ee); - size += tvh_strlen(ee->uri); - size += lang_str_size(ee->title); - size += lang_str_size(ee->subtitle); - size += lang_str_size(ee->summary); - size += lang_str_size(ee->description); - size += tvh_strlen(ee->image); - size += tvh_strlen(ee->epnum.text); - count++; - } - memoryinfo_update(my, size, count); -} - -static memoryinfo_t epg_memoryinfo_episodes = { - .my_name = "EPG Episodes", - .my_update = epg_memoryinfo_episodes_update -}; - static void epg_memoryinfo_broadcasts_update(memoryinfo_t *my) { channel_t *ch; @@ -186,7 +88,12 @@ static void epg_memoryinfo_broadcasts_update(memoryinfo_t *my) if (ch->ch_epg_parent) continue; RB_FOREACH(ebc, &ch->ch_epg_schedule, sched_link) { size += sizeof(*ebc); - size += tvh_strlen(ebc->uri); + size += tvh_strlen(ebc->image); + size += tvh_strlen(ebc->epnum.text); + size += tvh_strlen(ebc->episode_uri); + size += tvh_strlen(ebc->serieslink_uri); + size += lang_str_size(ebc->title); + size += lang_str_size(ebc->subtitle); size += lang_str_size(ebc->summary); size += lang_str_size(ebc->description); count++; @@ -215,7 +122,7 @@ static void epg_mmap_sigbus (int sig, siginfo_t *siginfo, void *ptr) */ void epg_init ( void ) { - int fd = -1, binary2 = 0, r; + int fd = -1, r; struct stat st; size_t remain; uint8_t *mem, *rp, *zlib_mem = NULL; @@ -224,7 +131,6 @@ void epg_init ( void ) struct sigaction act, oldact; char *sect = NULL; - memoryinfo_register(&epg_memoryinfo_episodes); memoryinfo_register(&epg_memoryinfo_broadcasts); /* Find the right file (and version) */ @@ -273,10 +179,9 @@ void epg_init ( void ) } #if ENABLE_ZLIB - if (remain > 12 && memcmp(rp, "\xff\xffGZIP0", 7) == 0 && + if (remain > 12 && memcmp(rp, "\xff\xffGZIP01", 8) == 0 && (rp[7] == '0' || rp[7] == '1')) { uint32_t orig = (rp[8] << 24) | (rp[9] << 16) | (rp[10] << 8) | rp[11]; - binary2 = rp[7] == '1'; tvhinfo(LS_EPGDB, "gzip format detected, inflating (ratio %.1f%% deflated size %zd)", (float)((remain * 100.0) / orig), remain); rp = zlib_mem = tvh_gzip_inflate(rp + 12, remain - 12, orig); @@ -293,11 +198,7 @@ void epg_init ( void ) /* Get message length */ size_t msglen = remain; htsmsg_t *m; - if (binary2) { - r = htsmsg_binary2_deserialize(&m, rp, &msglen, NULL); - } else { - r = htsmsg_binary_deserialize(&m, rp, &msglen, NULL); - } + r = htsmsg_binary2_deserialize(&m, rp, &msglen, NULL); /* Safety check */ if (r) { @@ -314,8 +215,8 @@ void epg_init ( void ) /* Process */ switch (ver) { - case 2: - _epgdb_v2_process(§, m, &stats); + case 3: + _epgdb_v3_process(§, m, &stats); break; default: break; @@ -339,7 +240,6 @@ void epg_init ( void ) /* Stats */ tvhinfo(LS_EPGDB, "loaded v%d", ver); tvhinfo(LS_EPGDB, " config %d", stats.config.total); - tvhinfo(LS_EPGDB, " episodes %d", stats.episodes.total); tvhinfo(LS_EPGDB, " broadcasts %d", stats.broadcasts.total); /* Close file */ @@ -358,7 +258,6 @@ void epg_done ( void ) CHANNEL_FOREACH(ch) epg_channel_unlink(ch); epg_skel_done(); - memoryinfo_unregister(&epg_memoryinfo_episodes); memoryinfo_unregister(&epg_memoryinfo_broadcasts); pthread_mutex_unlock(&global_lock); } @@ -374,12 +273,7 @@ static int _epg_write ( sbuf_t *sb, htsmsg_t *m ) void *msgdata; if (m) { int r; -#if ENABLE_ZLIB - if (config.epg_compress) - r = htsmsg_binary2_serialize(m, &msgdata, &msglen, 0x10000); - else -#endif - r = htsmsg_binary_serialize(m, &msgdata, &msglen, 0x10000); + r = htsmsg_binary2_serialize(m, &msgdata, &msglen, 0x10000); htsmsg_destroy(m); if (!r) { ret = 0; @@ -448,7 +342,6 @@ void epg_save_callback ( void *p ) void epg_save ( void ) { sbuf_t *sb = malloc(sizeof(*sb)); - epg_object_t *eo; epg_broadcast_t *ebc; channel_t *ch; epggrab_stats_t stats; @@ -468,11 +361,6 @@ void epg_save ( void ) memset(&stats, 0, sizeof(stats)); if ( _epg_write_sect(sb, "config") ) goto error; if (_epg_write(sb, epg_config_serialize())) goto error; - if ( _epg_write_sect(sb, "episodes") ) goto error; - RB_FOREACH(eo, &epg_episodes, uri_link) { - if (_epg_write(sb, epg_episode_serialize((epg_episode_t*)eo))) goto error; - stats.episodes.total++; - } if ( _epg_write_sect(sb, "broadcasts") ) goto error; CHANNEL_FOREACH(ch) { if (ch->ch_epg_parent) continue; @@ -486,7 +374,6 @@ void epg_save ( void ) /* Stats */ tvhinfo(LS_EPGDB, "queued to save (size %d)", sb->sb_ptr); - tvhinfo(LS_EPGDB, " episodes %d", stats.episodes.total); tvhinfo(LS_EPGDB, " broadcasts %d", stats.broadcasts.total); return; diff --git a/src/epggrab/module/eit.c b/src/epggrab/module/eit.c index af589edaf..a1dc23c26 100644 --- a/src/epggrab/module/eit.c +++ b/src/epggrab/module/eit.c @@ -609,10 +609,9 @@ static int _eit_process_event_one uint16_t eid; uint8_t running; epg_broadcast_t *ebc, _ebc; - epg_episode_t *ee = NULL, _ee; epg_running_t run; lang_str_t *title_copy = NULL; - uint32_t changes2 = 0, changes3 = 0; + epg_changes_t changes = 0; char tm1[32], tm2[32]; int short_target = ((eit_module_t *)mod)->short_target; @@ -625,7 +624,7 @@ static int _eit_process_event_one running = (ptr[10] >> 5) & 0x07; /* Find broadcast */ - ebc = epg_broadcast_find_by_time(ch, mod, start, stop, 1, &save2, &changes2); + ebc = epg_broadcast_find_by_time(ch, mod, start, stop, 1, &save2, &changes); tvhtrace(LS_TBL_EIT, "svc='%s', ch='%s', eid=%5d, tbl=%02x, running=%d, start=%s," " stop=%s, ebc=%p", svc->s_dvb_svcname ?: "(null)", @@ -644,17 +643,12 @@ static int _eit_process_event_one if (!ev->title) goto running; memset(&_ebc, 0, sizeof(_ebc)); - if (*ev->uri && (ee = epg_episode_find_by_uri(ev->uri, mod, 0, 0, NULL))) { - _ee = *ee; - } else { - memset(&_ee, 0, sizeof(_ee)); - } - _ebc.episode = &_ee; _ebc.dvb_eid = eid; _ebc.start = start; _ebc.stop = stop; + _ebc.episode_uri = ev->uri; _ebc.serieslink_uri = ev->suri; - _ee.title = title_copy = lang_str_copy(ev->title); + _ebc.title = title_copy = lang_str_copy(ev->title); ebc = epg_match_now_next(ch, &_ebc); tvhtrace(mod->subsys, "%s: running state only ebc=%p", svc->s_dvb_svcname ?: "(null)", ebc); @@ -667,72 +661,65 @@ static int _eit_process_event_one * Broadcast */ - *save |= epg_broadcast_set_dvb_eid(ebc, eid, &changes2); + *save |= epg_broadcast_set_dvb_eid(ebc, eid, &changes); /* Summary/Description */ if (ev->summary) if (short_target != 0 || (ev->subtitle && lang_str_compare(ev->summary, ev->subtitle))) - *save |= epg_broadcast_set_summary(ebc, ev->summary, &changes2); + *save |= epg_broadcast_set_summary(ebc, ev->summary, &changes); if (ev->desc) - *save |= epg_broadcast_set_description(ebc, ev->desc, &changes2); + *save |= epg_broadcast_set_description(ebc, ev->desc, &changes); /* Broadcast Metadata */ - *save |= epg_broadcast_set_is_hd(ebc, ev->hd, &changes2); - *save |= epg_broadcast_set_is_widescreen(ebc, ev->ws, &changes2); - *save |= epg_broadcast_set_is_audio_desc(ebc, ev->ad, &changes2); - *save |= epg_broadcast_set_is_subtitled(ebc, ev->st, &changes2); - *save |= epg_broadcast_set_is_deafsigned(ebc, ev->ds, &changes2); + *save |= epg_broadcast_set_is_hd(ebc, ev->hd, &changes); + *save |= epg_broadcast_set_is_widescreen(ebc, ev->ws, &changes); + *save |= epg_broadcast_set_is_audio_desc(ebc, ev->ad, &changes); + *save |= epg_broadcast_set_is_subtitled(ebc, ev->st, &changes); + *save |= epg_broadcast_set_is_deafsigned(ebc, ev->ds, &changes); /* * Series link */ if (*ev->suri) - *save |= epg_broadcast_set_serieslink_uri(ebc, ev->suri, &changes2); + *save |= epg_broadcast_set_serieslink_uri(ebc, ev->suri, &changes); /* * Episode */ /* Find episode */ - if (*ev->uri) { - ee = epg_episode_find_by_uri(ev->uri, mod, 1, save, &changes3); - } else { - ee = epg_episode_find_by_broadcast(ebc, mod, 1, save, &changes3); - } + if (*ev->uri) + *save |= epg_broadcast_set_episode_uri(ebc, ev->suri, &changes); /* Update Episode */ - if (ee) { - *save |= epg_broadcast_set_episode(ebc, ee, &changes2); - if (ev->is_new > 0) - *save |= epg_broadcast_set_is_new(ebc, ev->is_new - 1, &changes2); - *save |= epg_episode_set_is_bw(ee, ev->bw, &changes3); - if (ev->title) - *save |= epg_episode_set_title(ee, ev->title, &changes3); - if (ev->genre) - *save |= epg_episode_set_genre(ee, ev->genre, &changes3); - if (ev->parental) - *save |= epg_episode_set_age_rating(ee, ev->parental, &changes3); - if (ev->subtitle) - *save |= epg_episode_set_subtitle(ee, ev->subtitle, &changes3); - else if ((short_target == 0 || short_target == 2) && ev->summary) - *save |= epg_episode_set_subtitle(ee, ev->summary, &changes3); + if (ev->is_new > 0) + *save |= epg_broadcast_set_is_new(ebc, ev->is_new - 1, &changes); + *save |= epg_broadcast_set_is_bw(ebc, ev->bw, &changes); + if (ev->title) + *save |= epg_broadcast_set_title(ebc, ev->title, &changes); + if (ev->genre) + *save |= epg_broadcast_set_genre(ebc, ev->genre, &changes); + if (ev->parental) + *save |= epg_broadcast_set_age_rating(ebc, ev->parental, &changes); + if (ev->subtitle) + *save |= epg_broadcast_set_subtitle(ebc, ev->subtitle, &changes); + else if ((short_target == 0 || short_target == 2) && ev->summary) + *save |= epg_broadcast_set_subtitle(ebc, ev->summary, &changes); #if TODO_ADD_EXTRA - if (ev->extra) - *save |= epg_episode_set_extra(ee, extra, &changes3); + if (ev->extra) + *save |= epg_broadcast_set_extra(ebc, extra, &changes); #endif - /* save any found episode number */ - if (ev->en.s_num || ev->en.e_num || ev->en.p_num) - *save |= epg_episode_set_epnum(ee, &ev->en, &changes3); - if (ev->first_aired > 0) - *save |= epg_episode_set_first_aired(ee, ev->first_aired, &changes3); - if (ev->copyright_year > 0) - *save |= epg_episode_set_copyright_year(ee, ev->copyright_year, &changes3); - *save |= epg_episode_change_finish(ee, changes3, 0); - } - - *save |= epg_broadcast_change_finish(ebc, changes2, 0); + /* save any found episode number */ + if (ev->en.s_num || ev->en.e_num || ev->en.p_num) + *save |= epg_broadcast_set_epnum(ebc, &ev->en, &changes); + if (ev->first_aired > 0) + *save |= epg_broadcast_set_first_aired(ebc, ev->first_aired, &changes); + if (ev->copyright_year > 0) + *save |= epg_broadcast_set_copyright_year(ebc, ev->copyright_year, &changes); + + *save |= epg_broadcast_change_finish(ebc, changes, 0); running: diff --git a/src/epggrab/module/opentv.c b/src/epggrab/module/opentv.c index 8159c44dd..42cd25be4 100644 --- a/src/epggrab/module/opentv.c +++ b/src/epggrab/module/opentv.c @@ -293,11 +293,10 @@ opentv_parse_event_section_one int i, r, save = 0, merge; epggrab_module_t *src = (epggrab_module_t*)mod; epg_broadcast_t *ebc; - epg_episode_t *ee; opentv_event_t ev; char buffer[2048], *s; lang_str_t *ls; - uint32_t changes, changes2, changes3; + epg_changes_t changes; /* Loop around event entries */ i = 7; @@ -311,7 +310,7 @@ opentv_parse_event_section_one * Broadcast */ - merge = changes = changes2 = changes3 = 0; + merge = changes = 0; /* Find broadcast */ if (ev.start && ev.stop) { @@ -360,64 +359,59 @@ opentv_parse_event_section_one * Episode */ - if ((ee = epg_episode_find_by_broadcast(ebc, src, 1, &save, &changes3))) { - save |= epg_broadcast_set_episode(ebc, ee, &changes); - tvhdebug(LS_OPENTV, " find episode %p", ee); - if (ev.title) { - tvhdebug(LS_OPENTV, " title '%s'", ev.title); - - /* try to cleanup the title */ - if (eit_pattern_apply_list(buffer, sizeof(buffer), ev.title, lang, &mod->p_cleanup_title)) { - tvhtrace(LS_OPENTV, " clean title '%s'", buffer); - s = buffer; - } else { - s = ev.title; - } - ls = lang_str_create2(s, lang); - save |= epg_episode_set_title(ee, ls, &changes3); - lang_str_destroy(ls); + if (ev.title) { + tvhdebug(LS_OPENTV, " title '%s'", ev.title); + + /* try to cleanup the title */ + if (eit_pattern_apply_list(buffer, sizeof(buffer), ev.title, lang, &mod->p_cleanup_title)) { + tvhtrace(LS_OPENTV, " clean title '%s'", buffer); + s = buffer; + } else { + s = ev.title; } - if (ev.cat) { - epg_genre_list_t *egl = calloc(1, sizeof(epg_genre_list_t)); - epg_genre_list_add_by_eit(egl, ev.cat); - save |= epg_episode_set_genre(ee, egl, &changes3); - epg_genre_list_destroy(egl); + ls = lang_str_create2(s, lang); + save |= epg_broadcast_set_title(ebc, ls, &changes); + lang_str_destroy(ls); + } + if (ev.cat) { + epg_genre_list_t *egl = calloc(1, sizeof(epg_genre_list_t)); + epg_genre_list_add_by_eit(egl, ev.cat); + save |= epg_broadcast_set_genre(ebc, egl, &changes); + epg_genre_list_destroy(egl); + } + if (ev.summary) { + epg_episode_num_t en; + + memset(&en, 0, sizeof(en)); + /* search for season number */ + if (eit_pattern_apply_list(buffer, sizeof(buffer), ev.summary, lang, &mod->p_snum)) + if ((en.s_num = atoi(buffer))) + tvhtrace(LS_OPENTV," extract season number %d", en.s_num); + /* ...for episode number */ + if (eit_pattern_apply_list(buffer, sizeof(buffer), ev.summary, lang, &mod->p_enum)) + if ((en.e_num = atoi(buffer))) + tvhtrace(LS_OPENTV," extract episode number %d", en.e_num); + /* ...for part number */ + if (eit_pattern_apply_list(buffer, sizeof(buffer), ev.summary, lang, &mod->p_pnum)) { + if (buffer[0] >= 'a' && buffer[0] <= 'z') + en.p_num = buffer[0] - 'a' + 1; + else + if (buffer[0] >= 'A' && buffer[0] <= 'Z') + en.p_num = buffer[0] - 'A' + 1; + if (en.p_num) + tvhtrace(LS_OPENTV," extract part number %d", en.p_num); } - if (ev.summary) { - epg_episode_num_t en; - - memset(&en, 0, sizeof(en)); - /* search for season number */ - if (eit_pattern_apply_list(buffer, sizeof(buffer), ev.summary, lang, &mod->p_snum)) - if ((en.s_num = atoi(buffer))) - tvhtrace(LS_OPENTV," extract season number %d", en.s_num); - /* ...for episode number */ - if (eit_pattern_apply_list(buffer, sizeof(buffer), ev.summary, lang, &mod->p_enum)) - if ((en.e_num = atoi(buffer))) - tvhtrace(LS_OPENTV," extract episode number %d", en.e_num); - /* ...for part number */ - if (eit_pattern_apply_list(buffer, sizeof(buffer), ev.summary, lang, &mod->p_pnum)) { - if (buffer[0] >= 'a' && buffer[0] <= 'z') - en.p_num = buffer[0] - 'a' + 1; - else - if (buffer[0] >= 'A' && buffer[0] <= 'Z') - en.p_num = buffer[0] - 'A' + 1; - if (en.p_num) - tvhtrace(LS_OPENTV," extract part number %d", en.p_num); - } - /* save any found number */ - if (en.s_num || en.e_num || en.p_num) - save |= epg_episode_set_epnum(ee, &en, &changes3); - - /* ...for subtitle */ - if (eit_pattern_apply_list(buffer, sizeof(buffer), ev.summary, lang, &mod->p_subt)) { - tvhtrace(LS_OPENTV, " extract subtitle '%s'", buffer); - ls = lang_str_create2(buffer, lang); - save |= epg_episode_set_subtitle(ee, ls, &changes3); - lang_str_destroy(ls); - } + /* save any found number */ + if (en.s_num || en.e_num || en.p_num) + save |= epg_broadcast_set_epnum(ebc, &en, &changes); + + /* ...for subtitle */ + if (eit_pattern_apply_list(buffer, sizeof(buffer), ev.summary, lang, &mod->p_subt)) { + tvhtrace(LS_OPENTV, " extract subtitle '%s'", buffer); + ls = lang_str_create2(buffer, lang); + save |= epg_broadcast_set_subtitle(ebc, ls, &changes); + lang_str_destroy(ls); } - save |= epg_episode_change_finish(ee, changes3, merge); } save |= epg_broadcast_change_finish(ebc, changes, merge); diff --git a/src/epggrab/module/psip.c b/src/epggrab/module/psip.c index d07ccb22e..759b7f4cf 100644 --- a/src/epggrab/module/psip.c +++ b/src/epggrab/module/psip.c @@ -340,14 +340,13 @@ _psip_eit_callback_channel uint16_t eventid; uint32_t starttime, length; time_t start, stop; - int save = 0, save2, save3, i, size; + int save = 0, save2, i, size; uint8_t titlelen; unsigned int dlen; epg_broadcast_t *ebc; - epg_episode_t *ee; lang_str_t *title, *description; psip_desc_t *pd; - uint32_t changes2, changes3; + epg_changes_t changes2; epggrab_module_t *mod = (epggrab_module_t *)ps->ps_mod; for (i = 0; len >= 12 && i < count; len -= size, ptr += size, i++) { @@ -385,7 +384,7 @@ _psip_eit_callback_channel eventid, start, length, lang_str_get(title, NULL), titlelen); - save2 = save3 = changes2 = changes3 = 0; + save2 = changes2 = 0; ebc = epg_broadcast_find_by_time(ch, mod, start, stop, 1, &save2, &changes2); tvhtrace(LS_PSIP, " eid=%5d, start=%"PRItime_t", stop=%"PRItime_t", ebc=%p", @@ -403,16 +402,11 @@ _psip_eit_callback_channel } } - ee = epg_episode_find_by_broadcast(ebc, mod, 1, &save3, &changes3); - if (ee) { - save2 |= epg_broadcast_set_episode(ebc, ee, &changes2); - save3 |= epg_episode_set_title(ee, title, &changes3); - save3 |= epg_episode_change_finish(ee, changes3, 0); - } + save |= epg_broadcast_set_title(ebc, title, &changes2); save |= epg_broadcast_change_finish(ebc, changes2, 0); - save |= save2 | save3; + save |= save2; next: lang_str_destroy(title); @@ -548,7 +542,7 @@ _psip_ett_callback lang_str_t *description; idnode_list_mapping_t *ilm; channel_t *ch; - uint32_t changes; + epg_changes_t changes; /* Validate */ if (tableid != 0xcc) return -1; @@ -603,7 +597,7 @@ _psip_ett_callback save |= epg_broadcast_change_finish(ebc, changes, 1); tvhtrace(LS_PSIP, "0x%04x: ETT tableid 0x%04X [%s], eventid 0x%04X (%d) ['%s'], ver %d", mt->mt_pid, tsid, svc->s_dvb_svcname, eventid, eventid, - lang_str_get(ebc->episode->title, "eng"), ver); + lang_str_get(ebc->title, "eng"), ver); } else { found = 0; } diff --git a/src/epggrab/module/xmltv.c b/src/epggrab/module/xmltv.c index 9a3f90db8..accd4e474 100644 --- a/src/epggrab/module/xmltv.c +++ b/src/epggrab/module/xmltv.c @@ -260,7 +260,7 @@ static void get_episode_info */ static int xmltv_parse_vid_quality - ( epg_broadcast_t *ebc, htsmsg_t *m, int8_t *bw, uint32_t *changes ) + ( epg_broadcast_t *ebc, htsmsg_t *m, int8_t *bw, epg_changes_t *changes ) { int save = 0; int hd = 0, lines = 0, aspect = 0; @@ -320,7 +320,7 @@ xmltv_parse_vid_quality */ int xmltv_parse_accessibility - ( epg_broadcast_t *ebc, htsmsg_t *m, uint32_t *changes ) + ( epg_broadcast_t *ebc, htsmsg_t *m, epg_changes_t *changes ) { int save = 0; htsmsg_t *tag; @@ -348,7 +348,7 @@ xmltv_parse_accessibility */ static int _xmltv_parse_previously_shown ( epg_broadcast_t *ebc, time_t *first_aired, - htsmsg_t *tag, uint32_t *changes ) + htsmsg_t *tag, epg_changes_t *changes ) { int ret; const char *start; @@ -363,10 +363,10 @@ static int _xmltv_parse_previously_shown * Date finished, typically copyright date. */ static int _xmltv_parse_date_finished - ( epg_episode_t *ee, - htsmsg_t *tag, uint32_t *changes ) + ( epg_broadcast_t *ebc, + htsmsg_t *tag, epg_changes_t *changes ) { - if (!ee || !tag) return 0; + if (!ebc || !tag) return 0; const char *str = htsmsg_xml_get_cdata_str(tag, "date"); if (str) { /* Technically the date could contain information about month @@ -381,7 +381,7 @@ static int _xmltv_parse_date_finished const uint16_t year = atoi(year_buf); /* Sanity check the year before copying it over. */ if (year > 1800 && year < 2500) { - return epg_episode_set_copyright_year(ee, year, changes); + return epg_broadcast_set_copyright_year(ebc, year, changes); } } } @@ -396,14 +396,14 @@ static int _xmltv_parse_date_finished * */ static int _xmltv_parse_star_rating - ( epg_episode_t *ee, htsmsg_t *body, uint32_t *changes ) + ( epg_broadcast_t *ebc, htsmsg_t *body, epg_changes_t *changes ) { double a, b; htsmsg_t *stars, *tags; const char *s1, *s2; char *s1end, *s2end; - if (!ee || !body) return 0; + if (!ebc || !body) return 0; if (!(stars = htsmsg_get_map(body, "star-rating"))) return 0; if (!(tags = htsmsg_get_map(stars, "tags"))) return 0; if (!(s1 = htsmsg_xml_get_cdata_str(tags, "value"))) return 0; @@ -413,7 +413,7 @@ static int _xmltv_parse_star_rating b = strtod(s2 + 1, &s2end); if ( a == 0.0f || b == 0.0f) return 0; - return epg_episode_set_star_rating(ee, (100 * a) / b, changes); + return epg_broadcast_set_star_rating(ebc, (100 * a) / b, changes); } /* @@ -445,13 +445,13 @@ static int _xmltv_parse_star_rating * [rating system=advisory] values "strong sexual content","Language", etc */ static int _xmltv_parse_age_rating - ( epg_episode_t *ee, htsmsg_t *body, uint32_t *changes ) + ( epg_broadcast_t *ebc, htsmsg_t *body, epg_changes_t *changes ) { uint8_t age; htsmsg_t *rating, *tags; const char *s1; - if (!ee || !body) return 0; + if (!ebc || !body) return 0; htsmsg_field_t *f; HTSMSG_FOREACH(f, body) { @@ -476,7 +476,7 @@ static int _xmltv_parse_age_rating * rating of -10. */ if (age > 0 && age < 22) - return epg_episode_set_age_rating(ee, age, changes); + return epg_broadcast_set_age_rating(ebc, age, changes); } } } @@ -608,28 +608,30 @@ static int _xmltv_parse_programme_tags const int scrape_extra = ((epggrab_module_int_t *)mod)->xmltv_scrape_extra; const int scrape_onto_desc = ((epggrab_module_int_t *)mod)->xmltv_scrape_onto_desc; const int use_category_not_genre = ((epggrab_module_int_t *)mod)->xmltv_use_category_not_genre; - int save = 0, save2 = 0, save3 = 0; - epg_episode_t *ee = NULL; + int save = 0; + epg_changes_t changes = 0; epg_broadcast_t *ebc; epg_genre_list_t *egl; epg_episode_num_t epnum; memset(&epnum, 0, sizeof(epnum)); char *suri = NULL, *uri = NULL; + const char *s; lang_str_t *title = NULL; lang_str_t *desc = NULL; lang_str_t *summary = NULL; lang_str_t *subtitle = NULL; time_t first_aired = 0; int8_t bw = -1; - uint32_t changes = 0, changes2 = 0, changes3 = 0; /* * Broadcast */ - if (!(ebc = epg_broadcast_find_by_time(ch, mod, start, stop, 1, &save, &changes))) + ebc = epg_broadcast_find_by_time(ch, mod, start, stop, 1, &save, &changes); + if (!ebc) return 0; stats->broadcasts.total++; - if (save && (changes & EPG_CHANGED_CREATE)) stats->broadcasts.created++; + if (save && (changes & EPG_CHANGED_CREATE)) + stats->broadcasts.created++; /* Description (wait for episode first) */ _xmltv_parse_lang_str(&desc, tags, "desc"); @@ -643,17 +645,12 @@ static int _xmltv_parse_programme_tags string_list_t *category = _xmltv_make_str_list_from_matching(tags, "category"); string_list_t *keyword = _xmltv_make_str_list_from_matching(tags, "keyword"); - if (scrape_extra && credits) { - save3 |= epg_broadcast_set_credits(ebc, credits, &changes); - } - - if (scrape_extra && category) { - save3 |= epg_broadcast_set_category(ebc, category, &changes); - } - - if (scrape_extra && keyword) { - save3 |= epg_broadcast_set_keyword(ebc, keyword, &changes); - } + if (scrape_extra && credits) + save |= epg_broadcast_set_credits(ebc, credits, &changes); + if (scrape_extra && category) + save |= epg_broadcast_set_category(ebc, category, &changes); + if (scrape_extra && keyword) + save |= epg_broadcast_set_keyword(ebc, keyword, &changes); /* Convert the string list VAR to a human-readable csv and append * it to the desc with a prefix of NAME. @@ -688,14 +685,13 @@ static int _xmltv_parse_programme_tags #undef APPENDIT } /* desc */ - if (desc) { - save3 |= epg_broadcast_set_description(ebc, desc, &changes); - } /* desc */ + if (desc) + save |= epg_broadcast_set_description(ebc, desc, &changes); /* summary */ _xmltv_parse_lang_str(&summary, tags, "summary"); if (summary) - save3 |= epg_broadcast_set_summary(ebc, summary, &changes); + save |= epg_broadcast_set_summary(ebc, summary, &changes); /* Quality metadata */ save |= xmltv_parse_vid_quality(ebc, htsmsg_get_map(tags, "video"), &bw, &changes); @@ -720,62 +716,61 @@ static int _xmltv_parse_programme_tags * Series Link */ if (suri) { + s = ebc->serieslink_uri; save |= epg_broadcast_set_serieslink_uri(ebc, suri, &changes); free(suri); stats->seasons.total++; - if (save2 && (changes2 & EPG_CHANGED_CREATE)) stats->seasons.created++; + if (changes & EPG_CHANGED_SERIESLINK) { + if (s == NULL) + stats->seasons.created++; + else + stats->seasons.modified++; + } } /* * Episode */ if (uri) { - ee = epg_episode_find_by_uri(uri, mod, 1, &save3, &changes3); - free(uri); - uri = NULL; - } else { - ee = epg_episode_find_by_broadcast(ebc, mod, 1, &save3, &changes3); + s = ebc->episode_uri; + save |= epg_broadcast_set_episode_uri(ebc, uri, &changes); + stats->episodes.total++; + if (changes & EPG_CHANGED_EPISODE) { + if (s == NULL) + stats->episodes.created++; + else + stats->episodes.modified++; + } } - save |= epg_broadcast_set_episode(ebc, ee, &changes); - if (ee) stats->episodes.total++; - /* save3 is always set by epg_episode_find_by_uri call to - * _epg_object_set_grabber so need to also check for - * EPG_CHANGED_CREATE. - */ - if (save3 && (changes3 & EPG_CHANGED_CREATE)) stats->episodes.created++; - - if (ee) { - _xmltv_parse_lang_str(&title, tags, "title"); - _xmltv_parse_lang_str(&subtitle, tags, "sub-title"); - if (title) - save3 |= epg_episode_set_title(ee, title, &changes3); - if (subtitle) - save3 |= epg_episode_set_subtitle(ee, subtitle, &changes3); + _xmltv_parse_lang_str(&title, tags, "title"); + _xmltv_parse_lang_str(&subtitle, tags, "sub-title"); - if (!use_category_not_genre && (egl = _xmltv_parse_categories(tags))) { - save3 |= epg_episode_set_genre(ee, egl, &changes3); - epg_genre_list_destroy(egl); - } + if (title) + save |= epg_broadcast_set_title(ebc, title, &changes); + if (subtitle) + save |= epg_broadcast_set_subtitle(ebc, subtitle, &changes); - if (bw != -1) - save3 |= epg_episode_set_is_bw(ee, (uint8_t)bw, &changes3); + if (!use_category_not_genre && (egl = _xmltv_parse_categories(tags))) { + save |= epg_broadcast_set_genre(ebc, egl, &changes); + epg_genre_list_destroy(egl); + } - save3 |= epg_episode_set_epnum(ee, &epnum, &changes3); + if (bw != -1) + save |= epg_broadcast_set_is_bw(ebc, (uint8_t)bw, &changes); - save3 |= _xmltv_parse_star_rating(ee, tags, &changes3); + save |= epg_broadcast_set_epnum(ebc, &epnum, &changes); - save3 |= _xmltv_parse_date_finished(ee, tags, &changes3); + save |= _xmltv_parse_star_rating(ebc, tags, &changes); - save3 |= _xmltv_parse_age_rating(ee, tags, &changes3); + save |= _xmltv_parse_date_finished(ebc, tags, &changes); - if (icon) - save3 |= epg_episode_set_image(ee, icon, &changes3); + save |= _xmltv_parse_age_rating(ebc, tags, &changes); - save3 |= epg_episode_set_first_aired(ee, first_aired, &changes3); + if (icon) + save |= epg_broadcast_set_image(ebc, icon, &changes); - save3 |= epg_episode_change_finish(ee, changes3, 0); - } + save |= epg_broadcast_set_first_aired(ebc, first_aired, &changes); save |= epg_broadcast_change_finish(ebc, changes, 0); @@ -787,16 +782,15 @@ static int _xmltv_parse_programme_tags * the field exists in the message. This then means that the * "save" variable then indicate the record was modified. */ - if (save && !(changes & EPG_CHANGED_CREATE)) stats->broadcasts.modified++; - if (save2 && !(changes2 & EPG_CHANGED_CREATE)) stats->seasons.modified++; - if (save3 && !(changes3 & EPG_CHANGED_CREATE)) stats->episodes.modified++; + if (save && !(changes & EPG_CHANGED_CREATE)) + stats->broadcasts.modified++; /* Cleanup */ if (title) lang_str_destroy(title); if (subtitle) lang_str_destroy(subtitle); if (desc) lang_str_destroy(desc); if (summary) lang_str_destroy(summary); - return save | save2 | save3; + return save; } /** diff --git a/src/epggrab/private.h b/src/epggrab/private.h index 39e7e45c6..8b32c5b0f 100644 --- a/src/epggrab/private.h +++ b/src/epggrab/private.h @@ -178,7 +178,7 @@ epggrab_ota_service_del * *************************************************************************/ int xmltv_parse_accessibility - ( epg_broadcast_t *ebc, htsmsg_t *m, uint32_t *changes ); + ( epg_broadcast_t *ebc, htsmsg_t *m, epg_changes_t *changes ); /* Freesat huffman decoder */ size_t freesat_huffman_decode diff --git a/src/htsp_server.c b/src/htsp_server.c index 1120c4dfd..291f2e16c 100644 --- a/src/htsp_server.c +++ b/src/htsp_server.c @@ -1238,15 +1238,9 @@ htsp_build_event epg_genre_t *g; epg_episode_num_t epnum; const char *str; - epg_episode_t *ee = e->episode; /* Ignore? */ - if (update) { - int ignore = 1; - if (e->updated > update) ignore = 0; - else if (ee && ee->updated > update) ignore = 0; - if (ignore) return NULL; - } + if (update && e->updated <= update) return NULL; out = htsmsg_create_map(); @@ -1296,28 +1290,27 @@ htsp_build_event if (e->serieslink_uri) htsmsg_add_str(out, "serieslinkUri", e->serieslink_uri); - if (ee) { - htsmsg_add_u32(out, "episodeId", ee->id); - if (ee->uri && strncasecmp(ee->uri,"tvh://",6)) /* tvh:// uris are internal */ - htsmsg_add_str(out, "episodeUri", ee->uri); - if((g = LIST_FIRST(&ee->genre))) { - uint32_t code = g->code; - if (htsp->htsp_version < 6) code = (code >> 4) & 0xF; - htsmsg_add_u32(out, "contentType", code); - } - if (ee->age_rating) - htsmsg_add_u32(out, "ageRating", ee->age_rating); - if (ee->star_rating) - htsmsg_add_u32(out, "starRating", ee->star_rating); - if (ee->copyright_year) - htsmsg_add_u32(out, "copyrightYear", ee->copyright_year); - if (ee->first_aired) - htsmsg_add_s64(out, "firstAired", ee->first_aired); - epg_episode_get_epnum(ee, &epnum); - htsp_serialize_epnum(out, &epnum, NULL); - if (ee->image) - htsmsg_add_str(out, "image", ee->image); + /* tvh:// uris are internal */ + if (e->episode_uri && strncasecmp(e->episode_uri, "tvh://", 6)) + htsmsg_add_str(out, "episodeUri", e->episode_uri); + + if((g = LIST_FIRST(&e->genre))) { + uint32_t code = g->code; + if (htsp->htsp_version < 6) code = (code >> 4) & 0xF; + htsmsg_add_u32(out, "contentType", code); } + if (e->age_rating) + htsmsg_add_u32(out, "ageRating", e->age_rating); + if (e->star_rating) + htsmsg_add_u32(out, "starRating", e->star_rating); + if (e->copyright_year) + htsmsg_add_u32(out, "copyrightYear", e->copyright_year); + if (e->first_aired) + htsmsg_add_s64(out, "firstAired", e->first_aired); + epg_broadcast_get_epnum(e, &epnum); + htsp_serialize_epnum(out, &epnum, NULL); + if (e->image) + htsmsg_add_str(out, "image", e->image); if (e->channel) { LIST_FOREACH(de, &e->channel->ch_dvrs, de_channel_link) { diff --git a/src/muxer/muxer_mkv.c b/src/muxer/muxer_mkv.c index 0f1869224..10216ab60 100644 --- a/src/muxer/muxer_mkv.c +++ b/src/muxer/muxer_mkv.c @@ -738,17 +738,11 @@ _mk_build_metadata(const dvr_entry_t *de, const epg_broadcast_t *ebc, epg_genre_t eg0; struct tm tm; time_t t; - epg_episode_t *ee = NULL; - channel_t *ch = NULL; + channel_t *ch = ebc ? ebc->channel : NULL; lang_str_t *ls = NULL, *ls2 = NULL; const char *lang; const lang_code_list_t *langs; - - if (ebc) ee = ebc->episode; - else if (de && de->de_bcast) ee = de->de_bcast->episode; - - if (de) ch = de->de_channel; - else if (ebc) ch = ebc->channel; + epg_episode_num_t num; if (de || ebc) { localtime_r(de ? &de->de_start : &ebc->start, &tm); @@ -773,8 +767,8 @@ _mk_build_metadata(const dvr_entry_t *de, const epg_broadcast_t *ebc, memset(&eg0, 0, sizeof(eg0)); eg0.code = de->de_content_type; eg = &eg0; - } else if (ee) { - eg = LIST_FIRST(&ee->genre); + } else if (ebc) { + eg = LIST_FIRST(&ebc->genre); } if(eg && epg_genre_get_str(eg, 1, 0, ctype, 100, NULL)) addtag(q, build_tag_string("CONTENT_TYPE", ctype, NULL, 0, NULL)); @@ -783,15 +777,10 @@ _mk_build_metadata(const dvr_entry_t *de, const epg_broadcast_t *ebc, addtag(q, build_tag_string("TVCHANNEL", channel_get_name(ch, channel_blank_name), NULL, 0, NULL)); - if (ee && ee->summary) - ls = ee->summary; - else if (ebc && ebc->summary) + if (ebc && ebc->summary) ls = ebc->summary; - if(de && de->de_desc) ls2 = de->de_desc; - else if (ee && ee->description) - ls2 = ee->description; else if (ebc && ebc->description) ls2 = ebc->description; @@ -810,22 +799,19 @@ _mk_build_metadata(const dvr_entry_t *de, const epg_broadcast_t *ebc, addtag(q, build_tag_string("DESCRIPTION", e->str, e->lang, 0, NULL)); } - if (ee) { - epg_episode_num_t num; - epg_episode_get_epnum(ee, &num); - if(num.e_num) - addtag(q, build_tag_int("PART_NUMBER", num.e_num, - 0, NULL)); - if(num.s_num) - addtag(q, build_tag_int("PART_NUMBER", num.s_num, - 60, "SEASON")); - if(num.p_num) - addtag(q, build_tag_int("PART_NUMBER", num.p_num, - 40, "PART")); - if (num.text) - addtag(q, build_tag_string("SYNOPSIS", - num.text, NULL, 0, NULL)); - } + epg_broadcast_get_epnum(ebc, &num); + if(num.e_num) + addtag(q, build_tag_int("PART_NUMBER", num.e_num, + 0, NULL)); + if(num.s_num) + addtag(q, build_tag_int("PART_NUMBER", num.s_num, + 60, "SEASON")); + if(num.p_num) + addtag(q, build_tag_int("PART_NUMBER", num.p_num, + 40, "PART")); + if (num.text) + addtag(q, build_tag_string("SYNOPSIS", + num.text, NULL, 0, NULL)); if (comment) { lang = "eng"; diff --git a/src/webui/simpleui.c b/src/webui/simpleui.c index f2cc5fd54..64399e7d4 100644 --- a/src/webui/simpleui.c +++ b/src/webui/simpleui.c @@ -357,7 +357,7 @@ page_einfo(http_connection_t *hc, const char *remain, void *opaque) days[a.tm_wday], a.tm_mday, a.tm_mon + 1, a.tm_hour, a.tm_min, b.tm_hour, b.tm_min); - s = epg_episode_get_title(e->episode, lang); + s = epg_broadcast_get_title(e, lang); htsbuf_qprintf(hq, "
\"%s\": \"%s\"

", channel_get_name(e->channel, lang), s ?: ""); diff --git a/src/webui/xmltv.c b/src/webui/xmltv.c index 20bb9de92..9117b2382 100644 --- a/src/webui/xmltv.c +++ b/src/webui/xmltv.c @@ -106,21 +106,20 @@ http_xmltv_programme_one(htsbuf_queue_t *hq, const char *hostpath, channel_t *ch, epg_broadcast_t *ebc) { char start[32], stop[32], ubuf[UUID_HEX_SIZE]; - epg_episode_t *e = ebc->episode; lang_str_ele_t *lse; - if (e == NULL || e->title == NULL) return; + if (ebc->title == NULL) return; http_xmltv_time(start, ebc->start); http_xmltv_time(stop, ebc->stop); htsbuf_qprintf(hq, "\n", start, stop, idnode_uuid_as_str(&ch->ch_id, ubuf)); - RB_FOREACH(lse, e->title, link) { + RB_FOREACH(lse, ebc->title, link) { htsbuf_qprintf(hq, " ", lse->lang); htsbuf_append_and_escape_xml(hq, lse->str); htsbuf_append_str(hq, "\n"); } - if (e->subtitle) - RB_FOREACH(lse, e->subtitle, link) { + if (ebc->subtitle) + RB_FOREACH(lse, ebc->subtitle, link) { htsbuf_qprintf(hq, " ", lse->lang); htsbuf_append_and_escape_xml(hq, lse->str); htsbuf_append_str(hq, "\n");