.list = bouquet_class_get_list,
.opts = PO_RDONLY
},
+ {
+ .type = PT_STR,
+ .id = "epg_parent",
+ .name = N_("Reuse EPG from"),
+ .list = channel_class_get_list,
+ .off = offsetof(channel_t, ch_epg_parent),
+ .opts = PO_ADVANCED
+ },
{}
}
};
return ch;
}
+static void
+channel_epg_parent_unlink ( channel_t *ch )
+{
+ char uuid[UUID_HEX_SIZE];
+ idnode_uuid_as_str(&ch->ch_id, uuid);
+ RB_FOREACH(ch, &channels, ch_link)
+ if (ch->ch_epg_parent && !strcmp(ch->ch_epg_parent, uuid)) {
+ free(ch->ch_epg_parent);
+ ch->ch_epg_parent = NULL;
+ }
+}
+
void
channel_delete ( channel_t *ch, int delconf )
{
/* EPG */
epggrab_channel_rem(ch);
epg_channel_unlink(ch);
+ channel_epg_parent_unlink(ch);
/* HTSP */
htsp_channel_delete(ch);
/* Free memory */
RB_REMOVE(&channels, ch, ch_link);
idnode_unlink(&ch->ch_id);
+ free(ch->ch_epg_parent);
free(ch->ch_name);
free(ch->ch_icon);
free(ch);
LIST_HEAD(, th_subscription) ch_subscriptions;
/* EPG fields */
+ char *ch_epg_parent;
epg_broadcast_tree_t ch_epg_schedule;
epg_broadcast_t *ch_epg_now;
epg_broadcast_t *ch_epg_next;
gtimer_t ch_epg_timer_head;
gtimer_t ch_epg_timer_current;
- int ch_epgauto;
+ int ch_epgauto;
idnode_list_head_t ch_epggrab; /* 1 = epggrab channel, 2 = channel */
/* DVR */
#define channel_get_id(ch) idnode_get_short_uuid((&(ch)->ch_id))
+static inline channel_t *channel_epg_parent(channel_t *ch)
+{
+ if (ch->ch_epg_parent != NULL)
+ return channel_find_by_uuid(ch->ch_epg_parent);
+ return NULL;
+}
+
+static inline epg_broadcast_tree_t *channel_epg_schedule(channel_t *ch)
+{
+ if (ch->ch_epg_parent != NULL) {
+ channel_t *ch2 = channel_find_by_uuid(ch->ch_epg_parent);
+ if (ch2) return &ch2->ch_epg_schedule;
+ }
+ return &ch->ch_epg_schedule;
+}
+
#endif /* CHANNELS_H */
CHANNEL_FOREACH(ch) {
if (!ch->ch_enabled) continue;
- RB_FOREACH(e, &ch->ch_epg_schedule, sched_link) {
+ RB_FOREACH(e, channel_epg_schedule(ch), sched_link) {
if(autorec_cmp(dae, e)) {
enabled = 1;
if (disabled) {
e = NULL;
pre = (60 * dvr_entry_get_extra_time_pre(de)) - 30;
- RB_FOREACH(ev, &de->de_channel->ch_epg_schedule, sched_link) {
+ RB_FOREACH(ev, channel_epg_schedule(de->de_channel), sched_link) {
if (de->de_bcast == ev) continue;
if (ev->start - pre < dispatch_clock) continue;
if (dvr_entry_fuzzy_match(de, ev, 0, INT64_MAX))
/* Find match */
} else {
- RB_FOREACH(e, &e->channel->ch_epg_schedule, sched_link) {
+ RB_FOREACH(e, channel_epg_schedule(e->channel), sched_link) {
if (dvr_entry_fuzzy_match(de, e, e->dvb_eid,
de->de_config->dvr_update_window)) {
tvhtrace("dvr",
_eq_add_channel ( epg_query_t *eq, channel_t *ch )
{
epg_broadcast_t *ebc;
- RB_FOREACH(ebc, &ch->ch_epg_schedule, sched_link) {
+ RB_FOREACH(ebc, channel_epg_schedule(ch), sched_link) {
if (ebc->episode)
_eq_add(eq, ebc);
}
htsp_build_channel(channel_t *ch, const char *method, htsp_connection_t *htsp)
{
idnode_list_mapping_t *ilm;
+ channel_t *src = channel_epg_parent(ch) ?: ch;
channel_tag_t *ct;
service_t *t;
epg_broadcast_t *now, *next = NULL;
}
}
- now = ch->ch_epg_now;
- next = ch->ch_epg_next;
+ now = src->ch_epg_now;
+ next = src->ch_epg_next;
htsmsg_add_u32(out, "eventId", now ? now->id : 0);
htsmsg_add_u32(out, "nextEventId", next ? next->id : 0);
if (epg) {
CHANNEL_FOREACH(ch) {
if (!htsp_user_access_channel(htsp, ch)) continue;
- RB_FOREACH(ebc, &ch->ch_epg_schedule, sched_link) {
+ RB_FOREACH(ebc, channel_epg_schedule(ch), sched_link) {
if (epgMaxTime && ebc->start > epgMaxTime) break;
htsmsg_t *e = htsp_build_event(ebc, "eventAdd", lang, lastUpdate, htsp);
if (e) htsp_send_message(htsp, e, NULL);
/* Use event as starting point */
if (e || ch) {
+ ch = channel_epg_parent(ch) ?: ch;
if (!e) e = ch->ch_epg_now ?: ch->ch_epg_next;
/* Output */
events = htsmsg_create_list();
CHANNEL_FOREACH(ch) {
int num = numFollowing;
- RB_FOREACH(e, &ch->ch_epg_schedule, sched_link) {
+ RB_FOREACH(e, channel_epg_schedule(ch), sched_link) {
if (maxTime && e->start > maxTime) break;
htsmsg_add_msg(events, NULL, htsp_build_event(e, NULL, lang, 0, htsp));
if (num == 1) break;