{
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;
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);
/* 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);
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)) {
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
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);
double duration;
if (!e->channel) return 0;
- if (!e->episode) return 0;
if(dae->dae_enabled == 0 || dae->dae_weekdays == 0)
return 0;
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;
}
* 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 */
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)
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)
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;
}
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;
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);
}
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, "#"))
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
*/
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);
}
}
/* 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;
}
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;
}
}
}
/* 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;
}
/* 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;
}
/* 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));
}
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;
* 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;
}
{
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 *
{
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);
}
}
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);
}
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);
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. */
* 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;
}
}
/* 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;
}
} 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.
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");
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;
/* 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);
}
( 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);
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++;
}
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) {
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);
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) {
}
}
-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;
{
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);
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;
#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; \
#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; \
{
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:
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);
}
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,
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) {
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
* *************************************************************************/
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;
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;
}
static void _epg_broadcast_destroy ( void *eo )
{
epg_broadcast_t *ebc = eo;
+ epg_genre_t *eg;
char id[16];
if (ebc->_created) {
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);
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;
}
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))
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))
( 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,
/* 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);
*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);
}
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,
}
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,
}
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,
}
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,
}
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,
}
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,
}
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,
}
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,
}
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,
}
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,
}
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,
}
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);
}
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);
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;
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 )
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)
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)
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");
/* 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;
}
{
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;
_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;
*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))
*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;
_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 */
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)
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;
}
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)) {
}
}
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) {
_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
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;
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;
}
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;
}
*/
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;
*/
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;
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
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
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
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)
// 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
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".
///< 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 */
/* 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 */
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
#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;
* *************************************************************************/
/*
- * 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;
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++;
* 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;
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++;
*/
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;
struct sigaction act, oldact;
char *sect = NULL;
- memoryinfo_register(&epg_memoryinfo_episodes);
memoryinfo_register(&epg_memoryinfo_broadcasts);
/* Find the right file (and version) */
}
#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);
/* 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) {
/* Process */
switch (ver) {
- case 2:
- _epgdb_v2_process(§, m, &stats);
+ case 3:
+ _epgdb_v3_process(§, m, &stats);
break;
default:
break;
/* 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 */
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);
}
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;
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;
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;
/* 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;
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;
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)",
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);
* 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:
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;
* Broadcast
*/
- merge = changes = changes2 = changes3 = 0;
+ merge = changes = 0;
/* Find broadcast */
if (ev.start && ev.stop) {
* 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);
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++) {
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",
}
}
- 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);
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;
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;
}
*/
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;
*/
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;
*/
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;
* 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
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);
}
}
}
* </star-rating>
*/
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;
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);
}
/*
* [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) {
* 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);
}
}
}
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");
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.
#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);
* 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);
* 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;
}
/**
* *************************************************************************/
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
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();
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) {
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);
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));
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;
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";
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, "<hr><b>\"%s\": \"%s\"</b><br><br>",
channel_get_name(e->channel, lang), s ?: "");
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, "<programme start=\"%s\" stop=\"%s\" channel=\"%s\">\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, " <title lang=\"%s\">", lse->lang);
htsbuf_append_and_escape_xml(hq, lse->str);
htsbuf_append_str(hq, "</title>\n");
}
- if (e->subtitle)
- RB_FOREACH(lse, e->subtitle, link) {
+ if (ebc->subtitle)
+ RB_FOREACH(lse, ebc->subtitle, link) {
htsbuf_qprintf(hq, " <sub-title lang=\"%s\">", lse->lang);
htsbuf_append_and_escape_xml(hq, lse->str);
htsbuf_append_str(hq, "</sub-title>\n");