diff --git a/src/channels.c b/src/channels.c index 58ff4f6f..ad332630 100644 --- a/src/channels.c +++ b/src/channels.c @@ -33,6 +33,7 @@ #include "tvheadend.h" #include "psi.h" #include "epg.h" +#include "epggrab.h" #include "channels.h" #include "dtable.h" #include "notify.h" @@ -180,7 +181,7 @@ channel_create(const char *name, int number) assert(x == NULL); - epg_channel_map_add(ch); + epggrab_channel_add(ch); htsp_channel_add(ch); return ch; @@ -247,7 +248,7 @@ channel_load_one(htsmsg_t *c, int id) channel_set_name(ch, name); - epg_channel_map_add(ch); + epggrab_channel_add(ch); tvh_str_update(&ch->ch_icon, htsmsg_get_str(c, "icon")); @@ -337,7 +338,7 @@ channel_rename(channel_t *ch, const char *newname) RB_REMOVE(&channel_name_tree, ch, ch_name_link); channel_set_name(ch, newname); - epg_channel_map_mod(ch); + epggrab_channel_mod(ch); LIST_FOREACH(t, &ch->ch_services, s_ch_link) t->s_config_save(t); @@ -377,7 +378,8 @@ channel_delete(channel_t *ch) s->ths_channel = NULL; } - epg_channel_map_rem(ch); + epggrab_channel_rem(ch); + epg_channel_unlink(ch); hts_settings_remove("channels/%d", ch->ch_id); @@ -478,26 +480,6 @@ channel_set_number(channel_t *ch, int number) htsp_channel_update(ch); } -/** - * - */ -void -channel_set_epg_source(channel_t *ch, epg_channel_t *ec) -{ - lock_assert(&global_lock); - - if(ec == ch->ch_epg_channel) - return; - - ch->ch_epg_channel = ec; - - if(ec != NULL) - tvh_str_update(&ch->ch_icon, ec->icon); - - channel_save(ch); - htsp_channel_update(ch); -} - /** * */ diff --git a/src/channels.h b/src/channels.h index 34cf72ac..b6346cdb 100644 --- a/src/channels.h +++ b/src/channels.h @@ -19,6 +19,8 @@ #ifndef CHANNELS_H #define CHANNELS_H +#include "epg.h" + LIST_HEAD(channel_tag_mapping_list, channel_tag_mapping); TAILQ_HEAD(channel_tag_queue, channel_tag); @@ -43,8 +45,11 @@ typedef struct channel { LIST_HEAD(, service) ch_services; LIST_HEAD(, th_subscription) ch_subscriptions; - struct epg_channel *ch_epg_channel; - LIST_ENTRY(channel) ch_eulink; + /* EPG fields */ + epg_object_tree_t ch_epg_schedule; + epg_broadcast_t *ch_epg_now; + epg_broadcast_t *ch_epg_next; + gtimer_t ch_epg_timer; gtimer_t ch_epg_timer_head; gtimer_t ch_epg_timer_current; @@ -113,8 +118,6 @@ void channel_delete(channel_t *ch); void channel_merge(channel_t *dst, channel_t *src); -void channel_set_epg_source(channel_t *ch, struct epg_channel *ec); - void channel_set_epg_postpre_time(channel_t *ch, int pre, int mins); void channel_set_number(channel_t *ch, int number); diff --git a/src/dvr/dvr_autorec.c b/src/dvr/dvr_autorec.c index 549b2637..48a12167 100644 --- a/src/dvr/dvr_autorec.c +++ b/src/dvr/dvr_autorec.c @@ -66,7 +66,7 @@ autorec_cmp(dvr_autorec_entry_t *dae, epg_broadcast_t *e) { channel_tag_mapping_t *ctm; - if (!e->channel || !e->channel->channel) return 0; + if (!e->channel) return 0; if(dae->dae_enabled == 0 || dae->dae_weekdays == 0) return 0; @@ -77,12 +77,12 @@ autorec_cmp(dvr_autorec_entry_t *dae, epg_broadcast_t *e) return 0; // Avoid super wildcard match if(dae->dae_channel != NULL && - dae->dae_channel != e->channel->channel) + dae->dae_channel != e->channel) return 0; if(dae->dae_channel_tag != NULL) { LIST_FOREACH(ctm, &dae->dae_channel_tag->ct_ctms, ctm_tag_link) - if(ctm->ctm_channel == e->channel->channel) + if(ctm->ctm_channel == e->channel) break; if(ctm == NULL) return 0; diff --git a/src/dvr/dvr_db.c b/src/dvr/dvr_db.c index 4bb7a332..6da8fd76 100644 --- a/src/dvr/dvr_db.c +++ b/src/dvr/dvr_db.c @@ -330,11 +330,11 @@ dvr_entry_create_by_event(const char *config_name, epg_broadcast_t *e, const char *creator, dvr_autorec_entry_t *dae, dvr_prio_t pri) { - if(!e->channel || !e->channel->channel || !e->episode->title) + if(!e->channel || !e->episode->title) return NULL; return _dvr_entry_create(config_name, e, - e->channel->channel, e->start, e->stop, + e->channel, e->start, e->stop, e->episode->title, e->episode->description ? e->episode->description : e->episode->summary, @@ -724,7 +724,7 @@ dvr_entry_find_by_event(epg_broadcast_t *e) { dvr_entry_t *de; - LIST_FOREACH(de, &e->channel->channel->ch_dvrs, de_channel_link) + LIST_FOREACH(de, &e->channel->ch_dvrs, de_channel_link) if(de->de_bcast == e) return de; return NULL; } @@ -740,7 +740,7 @@ dvr_entry_find_by_event_fuzzy(epg_broadcast_t *e) if (e->episode->title == NULL) return NULL; - LIST_FOREACH(de, &e->channel->channel->ch_dvrs, de_channel_link) + LIST_FOREACH(de, &e->channel->ch_dvrs, de_channel_link) if ((abs(de->de_start - e->start) < 600) && (abs(de->de_stop - e->stop) < 600)) { return de; } diff --git a/src/dvr/mkmux.c b/src/dvr/mkmux.c index 851f45f6..2e8cfc67 100644 --- a/src/dvr/mkmux.c +++ b/src/dvr/mkmux.c @@ -563,8 +563,8 @@ mk_build_metadata2(const epg_broadcast_t *e) } #endif - if(e->channel->channel != NULL) - addtag(q, build_tag_string("TVCHANNEL", e->channel->channel->ch_name, 0, NULL)); + if(e->channel != NULL) + addtag(q, build_tag_string("TVCHANNEL", e->channel->ch_name, 0, NULL)); if(ee->title != NULL) addtag(q, build_tag_string("TITLE", ee->title, 0, NULL)); diff --git a/src/epg.h b/src/epg.h index 6eab8300..0e83ae56 100644 --- a/src/epg.h +++ b/src/epg.h @@ -26,9 +26,14 @@ #ifndef EPG_H #define EPG_H -#include "channels.h" #include "settings.h" +/* + * Forward decls + */ +struct channel; +struct channel_tag; + /* * Map types */ @@ -37,7 +42,6 @@ RB_HEAD(epg_object_tree, epg_object); RB_HEAD(epg_brand_tree, epg_brand); RB_HEAD(epg_season_tree, epg_season); RB_HEAD(epg_episode_tree, epg_episode); -RB_HEAD(epg_channel_tree, epg_channel); RB_HEAD(epg_broadcast_tree, epg_broadcast); /* @@ -48,13 +52,11 @@ typedef struct epg_brand epg_brand_t; typedef struct epg_season epg_season_t; typedef struct epg_episode epg_episode_t; typedef struct epg_broadcast epg_broadcast_t; -typedef struct epg_channel epg_channel_t; typedef struct epg_object_list epg_object_list_t; typedef struct epg_object_tree epg_object_tree_t; typedef struct epg_brand_tree epg_brand_tree_t; typedef struct epg_season_tree epg_season_tree_t; typedef struct epg_episode_tree epg_episode_tree_t; -typedef struct epg_channel_tree epg_channel_tree_t; typedef struct epg_broadcast_tree epg_broadcast_tree_t; /* ************************************************************************ @@ -241,7 +243,6 @@ typedef struct epg_broadcast { epg_object_t _; ///< Parent object - uint32_t dvb_id; ///< DVB identifier time_t start; ///< Start time time_t stop; ///< End time @@ -262,14 +263,14 @@ typedef struct epg_broadcast RB_ENTRY(epg_broadcast) elink; ///< Episode link epg_episode_t *episode; ///< Episode shown - epg_channel_t *channel; ///< Channel being broadcast on + struct channel *channel; ///< Channel being broadcast on } epg_broadcast_t; /* Lookup */ epg_broadcast_t *epg_broadcast_find_by_time - ( epg_channel_t *ch, time_t start, time_t stop, int create, int *save ); -epg_broadcast_t *epg_broadcast_find_by_id ( uint64_t id, epg_channel_t *ch ); + ( struct channel *ch, time_t start, time_t stop, int create, int *save ); +epg_broadcast_t *epg_broadcast_find_by_id ( uint64_t id, struct channel *ch ); /* Mutators */ int epg_broadcast_set_episode ( epg_broadcast_t *b, epg_episode_t *e ) @@ -287,50 +288,12 @@ epg_broadcast_t *epg_broadcast_deserialize * Channel - provides mapping from EPG channels to real channels * ***********************************************************************/ -/* Object */ -typedef struct epg_channel -{ - epg_object_t _; ///< Parent object - - char *name; ///< Channel name - char *icon; ///< Channel icon - char **sname; ///< DVB svc names (to map) - int **sid; ///< DVB svc ids (to map) - - epg_object_tree_t schedule; ///< List of broadcasts - LIST_ENTRY(epg_channel) umlink; ///< Unmapped channel link - channel_t *channel; ///< Link to real channel - - epg_broadcast_t *now; ///< Current broadcast - epg_broadcast_t *next; ///< Next broadcast - - gtimer_t expire; ///< Expiration timer -} epg_channel_t; - -/* Lookup */ -epg_channel_t *epg_channel_find_by_uri - ( const char *uri, int create, int *save ); -epg_channel_t *epg_channel_find_by_id ( uint64_t id ); - -/* Mutators */ -int epg_channel_set_name ( epg_channel_t *c, const char *n ) - __attribute__((warn_unused_result)); -int epg_channel_set_icon ( epg_channel_t *c, const char *i ) - __attribute__((warn_unused_result)); -int epg_channel_set_channel ( epg_channel_t *c, channel_t *ch ); - /* Accessors */ epg_broadcast_t *epg_channel_get_broadcast - ( epg_channel_t *ch, time_t start, time_t stop, int create, int *save ); + ( struct channel *ch, time_t start, time_t stop, int create, int *save ); -/* Serialization */ -htsmsg_t *epg_channel_serialize ( epg_channel_t *b ); -epg_channel_t *epg_channel_deserialize ( htsmsg_t *m, int create, int *save ); - -/* Channel mapping */ -void epg_channel_map_add ( channel_t *ch ); -void epg_channel_map_rem ( channel_t *ch ); -void epg_channel_map_mod ( channel_t *ch ); +/* Unlink */ +void epg_channel_unlink ( struct channel *ch ); /* ************************************************************************ * Querying @@ -352,8 +315,8 @@ void epg_query_free(epg_query_result_t *eqr); void epg_query_sort(epg_query_result_t *eqr); /* Query routines */ -void epg_query0(epg_query_result_t *eqr, channel_t *ch, channel_tag_t *ct, - uint8_t type, const char *title); +void epg_query0(epg_query_result_t *eqr, struct channel *ch, + struct channel_tag *ct, uint8_t type, const char *title); void epg_query(epg_query_result_t *eqr, const char *channel, const char *tag, const char *contentgroup, const char *title); diff --git a/src/epggrab.h b/src/epggrab.h index 2f4eefa4..dfc1dba3 100644 --- a/src/epggrab.h +++ b/src/epggrab.h @@ -37,6 +37,9 @@ typedef struct epggrab_module void (*disable) ( void ); htsmsg_t* (*grab) ( const char *opts ); int (*parse) ( htsmsg_t *data, epggrab_stats_t *stats ); + void (*ch_add) ( struct channel *ch ); + void (*ch_rem) ( struct channel *ch ); + void (*ch_mod) ( struct channel *ch ); } epggrab_module_t; /* @@ -87,4 +90,11 @@ void epggrab_set_simple ( uint32_t interval, epggrab_module_t* mod ); void epggrab_set_advanced ( uint32_t count, epggrab_sched_t* sched ); void epggrab_set_eit ( uint32_t eit ); +/* + * Channel handling + */ +void epggrab_channel_add ( struct channel *ch ); +void epggrab_channel_rem ( struct channel *ch ); +void epggrab_channel_mod ( struct channel *ch ); + #endif /* __EPGGRAB_H__ */ diff --git a/src/htsp.c b/src/htsp.c index 2d02c994..d3f7b036 100644 --- a/src/htsp.c +++ b/src/htsp.c @@ -310,12 +310,10 @@ htsp_build_channel(channel_t *ch, const char *method) if(ch->ch_icon != NULL) htsmsg_add_str(out, "channelIcon", ch->ch_icon); - if (ch->ch_epg_channel) { - now = ch->ch_epg_channel->now; - next = ch->ch_epg_channel->next; - htsmsg_add_u32(out, "eventId", now ? now->_.id : 0); - htsmsg_add_u32(out, "nextEventId", next ? next->_.id : 0); - } + now = ch->ch_epg_now; + next = ch->ch_epg_next; + htsmsg_add_u32(out, "eventId", now ? now->_.id : 0); + htsmsg_add_u32(out, "nextEventId", next ? next->_.id : 0); LIST_FOREACH(ctm, &ch->ch_ctms, ctm_channel_link) { ct = ctm->ctm_tag; @@ -757,7 +755,7 @@ htsp_build_event(epg_broadcast_t *e) out = htsmsg_create_map(); htsmsg_add_u32(out, "eventId", e->_.id); - htsmsg_add_u32(out, "channelId", e->channel->channel->ch_id); + htsmsg_add_u32(out, "channelId", e->channel->ch_id); htsmsg_add_u32(out, "start", e->start); htsmsg_add_u32(out, "stop", e->stop); if(e->episode->title != NULL) @@ -1425,8 +1423,8 @@ htsp_channel_update_current(channel_t *ch) htsmsg_add_str(m, "method", "channelUpdate"); htsmsg_add_u32(m, "channelId", ch->ch_id); - now = ch->ch_epg_channel->now; - next = ch->ch_epg_channel->next; + now = ch->ch_epg_now; + next = ch->ch_epg_next; htsmsg_add_u32(m, "eventId", now ? now->_.id : 0); htsmsg_add_u32(m, "nextEventId", next ? next->_.id : 0); htsp_async_send(m); diff --git a/src/webui/extjs.c b/src/webui/extjs.c index 7e87d59f..4702ecba 100644 --- a/src/webui/extjs.c +++ b/src/webui/extjs.c @@ -710,7 +710,7 @@ extjs_epg(http_connection_t *hc, const char *remain, void *opaque) for(i = start; i < end; i++) { e = eqr.eqr_array[i]; ee = e->episode; - ch = e->channel->channel; + ch = e->channel; if (!ch||!ee) continue; m = htsmsg_create_map(); @@ -787,7 +787,7 @@ extjs_epgrelated(http_connection_t *hc, const char *remain, void *opaque) /* Alternative broadcasts */ if (!strcmp(type, "alternative")) { RB_FOREACH(ebc, &ee->broadcasts, elink) { - ch = ebc->channel->channel; + ch = ebc->channel; if ( !ch ) continue; // skip something not viewable if ( ebc == e ) continue; // skip self count++; diff --git a/src/webui/simpleui.c b/src/webui/simpleui.c index 7733becc..a4a33020 100644 --- a/src/webui/simpleui.c +++ b/src/webui/simpleui.c @@ -229,9 +229,8 @@ page_einfo(http_connection_t *hc, const char *remain, void *opaque) days[a.tm_wday], a.tm_mday, a.tm_mon + 1, a.tm_hour, a.tm_min, b.tm_hour, b.tm_min); - // TODO: use real channel? htsbuf_qprintf(hq, "