diff --git a/src/epg.c b/src/epg.c
index 9f57662c..a63a2c51 100644
--- a/src/epg.c
+++ b/src/epg.c
@@ -36,11 +36,11 @@
#include "epggrab.h"
/* Element lists */
-struct epg_brand_tree epg_brands;
-struct epg_season_tree epg_seasons;
-struct epg_episode_tree epg_episodes;
-struct epg_channel_tree epg_channels;
-struct epg_broadcast_tree epg_broadcasts; // TODO: do we need this
+struct epg_object_tree epg_brands;
+struct epg_object_tree epg_seasons;
+struct epg_object_tree epg_episodes;
+struct epg_object_tree epg_channels;
+struct epg_object_tree epg_broadcasts;
/* Unlinked channels */
LIST_HEAD(epg_unlinked_channel_list1, epg_channel);
@@ -49,52 +49,40 @@ struct epg_unlinked_channel_list1 epg_unlinked_channels1;
struct epg_unlinked_channel_list2 epg_unlinked_channels2;
/* Global counters */
-static uint32_t _epg_channel_idx = 0;
-static uint32_t _epg_brand_idx = 0;
-static uint32_t _epg_season_idx = 0;
-static uint32_t _epg_episode_idx = 0;
-static uint32_t _epg_broadcast_idx = 0;
+static uint64_t _epg_object_idx = 0;
/* **************************************************************************
* Comparators
* *************************************************************************/
-static int eb_uri_cmp ( const epg_brand_t *a, const epg_brand_t *b )
+static int _uri_cmp ( const void *a, const void *b )
{
- return strcmp(a->eb_uri, b->eb_uri);
+ return strcmp(((epg_object_t*)a)->uri, ((epg_object_t*)b)->uri);
}
-static int es_uri_cmp ( const epg_season_t *a, const epg_season_t *b )
+#if TODO_MIGHT_NEED_LATER
+static int _id_cmp ( const void *a, const void *b )
{
- return strcmp(a->es_uri, b->es_uri);
+ return ((epg_object_t*)a)->id - ((epg_object_t*)b)->id;
}
+#endif
-static int ee_uri_cmp ( const epg_episode_t *a, const epg_episode_t *b )
-{
- return strcmp(a->ee_uri, b->ee_uri);
-}
-
-static int ec_uri_cmp ( const epg_channel_t *a, const epg_channel_t *b )
-{
- return strcmp(a->ec_uri, b->ec_uri);
-}
-
-static int ebc_win_cmp ( const epg_broadcast_t *a, const epg_broadcast_t *b )
-{
- if ( a->eb_start < b->eb_start ) return -1;
- if ( a->eb_start >= b->eb_stop ) return 1;
- return 0;
-}
-
-static int ptr_cmp ( void *a, void *b )
+static int _ptr_cmp ( const void *a, const void *b )
{
return a - b;
}
+static int _ebc_win_cmp ( const void *a, const void *b )
+{
+ if ( ((epg_broadcast_t*)a)->start < ((epg_broadcast_t*)b)->start ) return -1;
+ if ( ((epg_broadcast_t*)a)->start >= ((epg_broadcast_t*)b)->stop ) return 1;
+ return 0;
+}
+
static int _epg_channel_match ( epg_channel_t *ec, channel_t *ch )
{
int ret = 0;
- if ( ec->ec_name && !strcmp(ec->ec_name, ch->ch_name) ) ret = 1;
+ if ( ec->name && !strcmp(ec->name, ch->ch_name) ) ret = 1;
return ret;
}
@@ -104,6 +92,7 @@ static int _epg_channel_match ( epg_channel_t *ec, channel_t *ch )
static void _epg_dump ( void )
{
+ epg_object_t *eo;
epg_brand_t *eb;
epg_season_t *es;
epg_episode_t *ee;
@@ -112,37 +101,42 @@ static void _epg_dump ( void )
printf("dump epg\n");
/* Go down the brand/season/episode */
- RB_FOREACH(eb, &epg_brands, eb_link) {
- printf("BRAND: %p %s\n", eb, eb->eb_uri);
- RB_FOREACH(es, &eb->eb_seasons, es_blink) {
- printf(" SEASON: %p %s %d\n", es, es->es_uri, es->es_number);
- RB_FOREACH(ee, &es->es_episodes, ee_slink) {
- printf(" EPISODE: %p %s %d\n", ee, ee->ee_uri, ee->ee_number);
+ RB_FOREACH(eo, &epg_brands, glink) {
+ eb = (epg_brand_t*)eo;
+ printf("BRAND: %p %s\n", eb, eb->_.uri);
+ RB_FOREACH(es, &eb->seasons, blink) {
+ printf(" SEASON: %p %s %d\n", es, es->_.uri, es->number);
+ RB_FOREACH(ee, &es->episodes, slink) {
+ printf(" EPISODE: %p %s %d\n", ee, ee->_.uri, ee->number);
}
}
- RB_FOREACH(ee, &eb->eb_episodes, ee_blink) {
- if ( !ee->ee_season ) printf(" EPISODE: %p %s %d\n", ee, ee->ee_uri, ee->ee_number);
+ RB_FOREACH(ee, &eb->episodes, blink) {
+ if ( !ee->season ) printf(" EPISODE: %p %s %d\n", ee, ee->_.uri, ee->number);
}
}
- RB_FOREACH(es, &epg_seasons, es_link) {
- if ( !es->es_brand ) {
- printf("SEASON: %p %s %d\n", es, es->es_uri, es->es_number);
- RB_FOREACH(ee, &es->es_episodes, ee_slink) {
- printf(" EPISODE: %p %s %d\n", ee, ee->ee_uri, ee->ee_number);
+ RB_FOREACH(eo, &epg_seasons, glink) {
+ es = (epg_season_t*)eo;
+ if ( !es->brand ) {
+ printf("SEASON: %p %s %d\n", es, es->_.uri, es->number);
+ RB_FOREACH(ee, &es->episodes, slink) {
+ printf(" EPISODE: %p %s %d\n", ee, ee->_.uri, ee->number);
}
}
}
- RB_FOREACH(ee, &epg_episodes, ee_link) {
- if ( !ee->ee_brand && !ee->ee_season ) {
- printf("EPISODE: %p %s %d\n", ee, ee->ee_uri, ee->ee_number);
+ RB_FOREACH(eo, &epg_episodes, glink) {
+ ee = (epg_episode_t*)eo;
+ if ( !ee->brand && !ee->season ) {
+ printf("EPISODE: %p %s %d\n", ee, ee->_.uri, ee->number);
}
}
- RB_FOREACH(ec, &epg_channels, ec_link) {
- printf("CHANNEL: %s\n", ec->ec_uri);
- RB_FOREACH(ebc, &ec->ec_schedule, eb_slink) {
- if ( ebc->eb_episode ) {
- printf(" BROADCAST: %s @ %ld to %ld\n", ebc->eb_episode->ee_uri,
- ebc->eb_start, ebc->eb_stop);
+ RB_FOREACH(eo, &epg_channels, glink) {
+ ec = (epg_channel_t*)eo;
+ printf("CHANNEL: %s\n", ec->_.uri);
+ RB_FOREACH(eo, &ec->schedule, glink) {
+ ebc = (epg_broadcast_t*)eo;
+ if ( ebc->episode ) {
+ printf(" BROADCAST: %s @ %ld to %ld\n", ebc->episode->_.uri,
+ ebc->start, ebc->stop);
}
}
}
@@ -184,38 +178,35 @@ static int _epg_write_sect ( int fd, const char *sect )
void epg_save ( void )
{
int fd;
- epg_brand_t *eb;
- epg_season_t *es;
- epg_episode_t *ee;
+ epg_object_t *eo;
epg_channel_t *ec;
- epg_broadcast_t *ebc;
- printf("EPG save\n");
// TODO: requires markers in the file or some other means of
// determining where the various object types are?
fd = hts_settings_open_file(1, "epgdb");
/* Channels */
if ( _epg_write_sect(fd, "channels") ) return;
- RB_FOREACH(ec, &epg_channels, ec_link) {
- if (_epg_write(fd, epg_channel_serialize(ec))) return;
+ RB_FOREACH(eo, &epg_channels, glink) {
+ if (_epg_write(fd, epg_channel_serialize((epg_channel_t*)eo))) return;
}
if ( _epg_write_sect(fd, "brands") ) return;
- RB_FOREACH(eb, &epg_brands, eb_link) {
- if (_epg_write(fd, epg_brand_serialize(eb))) return;
+ RB_FOREACH(eo, &epg_brands, glink) {
+ if (_epg_write(fd, epg_brand_serialize((epg_brand_t*)eo))) return;
}
if ( _epg_write_sect(fd, "seasons") ) return;
- RB_FOREACH(es, &epg_seasons, es_link) {
- if (_epg_write(fd, epg_season_serialize(es))) return;
+ RB_FOREACH(eo, &epg_seasons, glink) {
+ if (_epg_write(fd, epg_season_serialize((epg_season_t*)eo))) return;
}
if ( _epg_write_sect(fd, "episodes") ) return;
- RB_FOREACH(ee, &epg_episodes, ee_link) {
- if (_epg_write(fd, epg_episode_serialize(ee))) return;
+ RB_FOREACH(eo, &epg_episodes, glink) {
+ if (_epg_write(fd, epg_episode_serialize((epg_episode_t*)eo))) return;
}
if ( _epg_write_sect(fd, "broadcasts") ) return;
- RB_FOREACH(ec, &epg_channels, ec_link) {
- RB_FOREACH(ebc, &ec->ec_schedule, eb_slink) {
- if (_epg_write(fd, epg_broadcast_serialize(ebc))) return;
+ RB_FOREACH(eo, &epg_channels, glink) {
+ ec = (epg_channel_t*)eo;
+ RB_FOREACH(eo, &ec->schedule, glink) {
+ if (_epg_write(fd, epg_broadcast_serialize((epg_broadcast_t*)eo))) return;
}
}
}
@@ -329,24 +320,28 @@ void epg_updated ( void )
void epg_add_channel ( channel_t *ch )
{
+#if TODO_REDO_CHANNEL_LINKING
epg_channel_t *ec;
LIST_INSERT_HEAD(&epg_unlinked_channels2, ch, ch_eulink);
- LIST_FOREACH(ec, &epg_unlinked_channels1, ec_ulink) {
+ LIST_FOREACH(ec, &epg_unlinked_channels1, ulink) {
if ( _epg_channel_match(ec, ch) ) {
epg_channel_set_channel(ec, ch);
break;
}
}
+#endif
}
void epg_rem_channel ( channel_t *ch )
{
+#if TODO_REDO_CHANNEL_LINKING
if ( ch->ch_epg_channel ) {
- ch->ch_epg_channel->ec_channel = NULL;
+ ch->ch_epg_channel->channel = NULL;
// TODO: free the channel?
} else {
LIST_REMOVE(ch, ch_eulink);
}
+#endif
}
void epg_mod_channel ( channel_t *ch )
@@ -355,57 +350,90 @@ void epg_mod_channel ( channel_t *ch )
}
+/* **************************************************************************
+ * Object
+ * *************************************************************************/
+
+static epg_object_t *_epg_object_find
+ ( int create, int *save, epg_object_tree_t *tree,
+ epg_object_t *skel, int (*cmp) (const void*,const void*))
+{
+ epg_object_t *eo;
+
+ /* Find */
+ if ( !create ) {
+ eo = RB_FIND(tree, skel, glink, cmp);
+
+ /* Create */
+ } else {
+ eo = RB_INSERT_SORTED(tree, skel, glink, cmp);
+ if ( eo == NULL ) {
+ *save |= 1;
+ eo = skel;
+ skel = NULL;
+ _epg_object_idx++;
+ }
+ }
+
+ return eo;
+}
+
+static epg_object_t *_epg_object_find_by_uri
+ ( const char *uri, int create, int *save,
+ epg_object_tree_t *tree, size_t size )
+{
+ int save2 = 0;
+ epg_object_t *eo;
+ static epg_object_t* skel = NULL;
+
+ lock_assert(&global_lock); // pointless!
+
+ if ( skel == NULL ) skel = calloc(1, size);
+ skel->uri = (char*)uri;
+ skel->id = _epg_object_idx;
+ // TODO: need to add function pointers
+
+ eo = _epg_object_find(create, &save2, tree, skel, _uri_cmp);
+ if (save2) eo->uri = strdup(uri);
+ *save |= save2;
+ return eo;
+}
+
+static epg_object_t *_epg_object_find_by_id
+ ( uint64_t id, epg_object_tree_t *tree )
+{
+ epg_object_t *eo;
+ if (!tree) return NULL; // TODO: use a global list?
+ RB_FOREACH(eo, tree, glink) {
+ if ( eo->id == id ) return eo;
+ }
+ return NULL;
+}
+
/* **************************************************************************
* Brand
* *************************************************************************/
epg_brand_t* epg_brand_find_by_uri
- ( const char *id, int create, int *save )
+ ( const char *uri, int create, int *save )
{
- epg_brand_t *eb;
- static epg_brand_t* skel = NULL;
-
- lock_assert(&global_lock); // pointless!
-
- if ( skel == NULL ) skel = calloc(1, sizeof(epg_brand_t));
- skel->eb_uri = (char*)id;
- skel->eb_id = _epg_brand_idx;
-
- /* Find */
- if ( !create ) {
- eb = RB_FIND(&epg_brands, skel, eb_link, eb_uri_cmp);
-
- /* Create */
- } else {
- eb = RB_INSERT_SORTED(&epg_brands, skel, eb_link, eb_uri_cmp);
- if ( eb == NULL ) {
- *save |= 1;
- eb = skel;
- skel = NULL;
- eb->eb_uri = strdup(id);
- _epg_brand_idx++;
- }
- }
-
- return eb;
+ return (epg_brand_t*)
+ _epg_object_find_by_uri(uri, create, save,
+ &epg_brands, sizeof(epg_brand_t));
}
-epg_brand_t *epg_brand_find_by_id ( uint32_t id )
+epg_brand_t *epg_brand_find_by_id ( uint64_t id )
{
- epg_brand_t *eb;
- RB_FOREACH(eb, &epg_brands, eb_link) {
- if ( eb->eb_id == id ) return eb;
- }
- return NULL;
+ return (epg_brand_t*)_epg_object_find_by_id(id, &epg_brands);
}
int epg_brand_set_title ( epg_brand_t *brand, const char *title )
{
int save = 0;
if ( !brand || !title ) return 0;
- if ( !brand->eb_title || strcmp(brand->eb_title, title) ) {
- if ( brand->eb_title ) free(brand->eb_title);
- brand->eb_title = strdup(title);
+ if ( !brand->title || strcmp(brand->title, title) ) {
+ if ( brand->title ) free(brand->title);
+ brand->title = strdup(title);
save = 1;
}
return save;
@@ -415,9 +443,9 @@ int epg_brand_set_summary ( epg_brand_t *brand, const char *summary )
{
int save = 0;
if ( !brand || !summary ) return 0;
- if ( !brand->eb_summary || strcmp(brand->eb_summary, summary) ) {
- if ( brand->eb_summary ) free(brand->eb_summary);
- brand->eb_summary = strdup(summary);
+ if ( !brand->summary || strcmp(brand->summary, summary) ) {
+ if ( brand->summary ) free(brand->summary);
+ brand->summary = strdup(summary);
save = 1;
}
return save;
@@ -428,8 +456,8 @@ int epg_brand_set_season_count ( epg_brand_t *brand, uint16_t count )
// TODO: could set only if less?
int save = 0;
if ( !brand || !count ) return 0;
- if ( brand->eb_season_count != count ) {
- brand->eb_season_count = count;
+ if ( brand->season_count != count ) {
+ brand->season_count = count;
save = 1;
}
return save;
@@ -440,12 +468,11 @@ int epg_brand_add_season ( epg_brand_t *brand, epg_season_t *season, int u )
int save = 0;
epg_season_t *es;
if ( !brand || !season ) return 0;
- es = RB_INSERT_SORTED(&brand->eb_seasons, season, es_blink, es_uri_cmp);
+ es = RB_INSERT_SORTED(&brand->seasons, season, blink, _uri_cmp);
if ( es == NULL ) {
if ( u ) save |= epg_season_set_brand(season, brand, 0);
save = 1;
}
- // TODO?: else assert(es == season)
return save;
}
@@ -454,11 +481,10 @@ int epg_brand_rem_season ( epg_brand_t *brand, epg_season_t *season, int u )
int save = 0;
epg_season_t *es;
if ( !brand || !season ) return 0;
- es = RB_FIND(&brand->eb_seasons, season, es_blink, es_uri_cmp);
+ es = RB_FIND(&brand->seasons, season, blink, _uri_cmp);
if ( es != NULL ) {
- // TODO: assert(es == season)
if ( u ) save |= epg_season_set_brand(season, NULL, 0); // TODO: this will do nothing
- RB_REMOVE(&brand->eb_seasons, season, es_blink);
+ RB_REMOVE(&brand->seasons, season, blink);
save = 1;
}
return save;
@@ -469,12 +495,11 @@ int epg_brand_add_episode ( epg_brand_t *brand, epg_episode_t *episode, int u )
int save = 0;
epg_episode_t *ee;
if ( !brand || !episode ) return 0;
- ee = RB_INSERT_SORTED(&brand->eb_episodes, episode, ee_blink, ee_uri_cmp);
+ ee = RB_INSERT_SORTED(&brand->episodes, episode, blink, _uri_cmp);
if ( ee == NULL ) {
if ( u ) save |= epg_episode_set_brand(episode, brand, 0);
save = 1;
}
- // TODO?: else assert(ee == episode)
return save;
}
@@ -483,11 +508,10 @@ int epg_brand_rem_episode ( epg_brand_t *brand, epg_episode_t *episode, int u )
int save = 0;
epg_episode_t *ee;
if ( !brand || !episode ) return 0;
- ee = RB_FIND(&brand->eb_episodes, episode, ee_blink, ee_uri_cmp);
+ ee = RB_FIND(&brand->episodes, episode, blink, _uri_cmp);
if ( ee != NULL ) {
- // TODO?: assert(ee == episode)
if ( u ) save |= epg_episode_set_brand(episode, NULL, 0); // TODO: will do nothing
- RB_REMOVE(&brand->eb_episodes, episode, ee_blink);
+ RB_REMOVE(&brand->episodes, episode, blink);
save = 1;
}
return save;
@@ -496,15 +520,16 @@ int epg_brand_rem_episode ( epg_brand_t *brand, epg_episode_t *episode, int u )
htsmsg_t *epg_brand_serialize ( epg_brand_t *brand )
{
htsmsg_t *m;
- if ( !brand || !brand->eb_uri ) return NULL;
+ if ( !brand || !brand->_.uri ) return NULL;
m = htsmsg_create_map();
- htsmsg_add_str(m, "uri", brand->eb_uri);
- if (brand->eb_title)
- htsmsg_add_str(m, "title", brand->eb_title);
- if (brand->eb_summary)
- htsmsg_add_str(m, "summary", brand->eb_summary);
- if (brand->eb_season_count)
- htsmsg_add_u32(m, "season-count", brand->eb_season_count);
+ // TODO: generic serialize?
+ htsmsg_add_str(m, "uri", brand->_.uri);
+ if (brand->title)
+ htsmsg_add_str(m, "title", brand->title);
+ if (brand->summary)
+ htsmsg_add_str(m, "summary", brand->summary);
+ if (brand->season_count)
+ htsmsg_add_u32(m, "season-count", brand->season_count);
return m;
}
@@ -513,7 +538,8 @@ epg_brand_t *epg_brand_deserialize ( htsmsg_t *m, int create, int *save )
epg_brand_t *eb;
uint32_t u32;
const char *str;
-
+
+ // TODO: generic deserialize?
if ( !(str = htsmsg_get_str(m, "uri")) ) return NULL;
if ( !(eb = epg_brand_find_by_uri(str, create, save)) ) return NULL;
@@ -532,52 +558,25 @@ epg_brand_t *epg_brand_deserialize ( htsmsg_t *m, int create, int *save )
* *************************************************************************/
epg_season_t* epg_season_find_by_uri
- ( const char *id, int create, int *save )
+ ( const char *uri, int create, int *save )
{
- epg_season_t *es;
- static epg_season_t* skel = NULL;
-
- lock_assert(&global_lock); // pointless!
-
- if ( skel == NULL ) skel = calloc(1, sizeof(epg_season_t));
- skel->es_uri = (char*)id;
- skel->es_id = _epg_season_idx;
-
- /* Find */
- if ( !create ) {
- es = RB_FIND(&epg_seasons, skel, es_link, es_uri_cmp);
-
- /* Create */
- } else {
- es = RB_INSERT_SORTED(&epg_seasons, skel, es_link, es_uri_cmp);
- if ( es == NULL ) {
- *save |= 1;
- es = skel;
- skel = NULL;
- es->es_uri = strdup(id);
- _epg_season_idx++;
- }
- }
-
- return es;
+ return (epg_season_t*)
+ _epg_object_find_by_uri(uri, create, save,
+ &epg_seasons, sizeof(epg_season_t));
}
-epg_season_t *epg_season_find_by_id ( uint32_t id )
+epg_season_t *epg_season_find_by_id ( uint64_t id )
{
- epg_season_t *es;
- RB_FOREACH(es, &epg_seasons, es_link) {
- if ( es->es_id == id ) return es;
- }
- return NULL;
+ return (epg_season_t*)_epg_object_find_by_id(id, &epg_seasons);
}
int epg_season_set_summary ( epg_season_t *season, const char *summary )
{
int save = 0;
if ( !season || !summary ) return 0;
- if ( !season->es_summary || strcmp(season->es_summary, summary) ) {
- if ( season->es_summary ) free(season->es_summary);
- season->es_summary = strdup(summary);
+ if ( !season->summary || strcmp(season->summary, summary) ) {
+ if ( season->summary ) free(season->summary);
+ season->summary = strdup(summary);
save = 1;
}
return save;
@@ -588,8 +587,8 @@ int epg_season_set_episode_count ( epg_season_t *season, uint16_t count )
int save = 0;
if ( !season || !count ) return 0;
// TODO: should we only update if number is larger
- if ( season->es_episode_count != count ) {
- season->es_episode_count = count;
+ if ( season->episode_count != count ) {
+ season->episode_count = count;
save = 1;
}
return save;
@@ -599,8 +598,8 @@ int epg_season_set_number ( epg_season_t *season, uint16_t number )
{
int save = 0;
if ( !season || !number ) return 0;
- if ( season->es_number != number ) {
- season->es_number = number;
+ if ( season->number != number ) {
+ season->number = number;
save = 1;
}
return save;
@@ -610,10 +609,10 @@ int epg_season_set_brand ( epg_season_t *season, epg_brand_t *brand, int u )
{
int save = 0;
if ( !season || !brand ) return 0;
- if ( season->es_brand != brand ) {
- if ( u ) save |= epg_brand_rem_season(season->es_brand, season, 0);
- season->es_brand = brand;
- if ( u ) save |= epg_brand_add_season(season->es_brand, season, 0);
+ if ( season->brand != brand ) {
+ if ( u ) save |= epg_brand_rem_season(season->brand, season, 0);
+ season->brand = brand;
+ if ( u ) save |= epg_brand_add_season(season->brand, season, 0);
save = 1;
}
return save;
@@ -625,7 +624,7 @@ int epg_season_add_episode
int save = 0;
epg_episode_t *ee;
if ( !season || !episode ) return 0;
- ee = RB_INSERT_SORTED(&season->es_episodes, episode, ee_slink, ee_uri_cmp);
+ ee = RB_INSERT_SORTED(&season->episodes, episode, slink, _uri_cmp);
if ( ee == NULL ) {
if ( u ) save |= epg_episode_set_season(episode, season, 0);
save = 1;
@@ -640,11 +639,11 @@ int epg_season_rem_episode
int save = 0;
epg_episode_t *ee;
if ( !season || !episode ) return 0;
- ee = RB_FIND(&season->es_episodes, episode, ee_slink, ee_uri_cmp);
+ ee = RB_FIND(&season->episodes, episode, slink, _uri_cmp);
if ( ee != NULL ) {
// TODO?: assert(ee == episode)
if ( u ) save |= epg_episode_set_season(episode, NULL, 0); // does nothing
- RB_REMOVE(&season->es_episodes, episode, ee_slink);
+ RB_REMOVE(&season->episodes, episode, slink);
save = 1;
}
return save;
@@ -653,17 +652,18 @@ int epg_season_rem_episode
htsmsg_t *epg_season_serialize ( epg_season_t *season )
{
htsmsg_t *m;
- if (!season || !season->es_uri) return NULL;
+ if (!season || !season->_.uri) return NULL;
m = htsmsg_create_map();
- htsmsg_add_str(m, "uri", season->es_uri);
- if (season->es_summary)
- htsmsg_add_str(m, "summary", season->es_summary);
- if (season->es_number)
- htsmsg_add_u32(m, "number", season->es_number);
- if (season->es_episode_count)
- htsmsg_add_u32(m, "episode-count", season->es_episode_count);
- if (season->es_brand)
- htsmsg_add_str(m, "brand", season->es_brand->eb_uri);
+ // TODO: generic
+ htsmsg_add_str(m, "uri", season->_.uri);
+ if (season->summary)
+ htsmsg_add_str(m, "summary", season->summary);
+ if (season->number)
+ htsmsg_add_u32(m, "number", season->number);
+ if (season->episode_count)
+ htsmsg_add_u32(m, "episode-count", season->episode_count);
+ if (season->brand)
+ htsmsg_add_str(m, "brand", season->brand->_.uri);
return m;
}
@@ -674,6 +674,7 @@ epg_season_t *epg_season_deserialize ( htsmsg_t *m, int create, int *save )
uint32_t u32;
const char *str;
+ // TODO: generic
if ( !(str = htsmsg_get_str(m, "uri")) ) return NULL;
if ( !(es = epg_season_find_by_uri(str, create, save)) ) return NULL;
@@ -696,52 +697,25 @@ epg_season_t *epg_season_deserialize ( htsmsg_t *m, int create, int *save )
* *************************************************************************/
epg_episode_t* epg_episode_find_by_uri
- ( const char *id, int create, int *save )
+ ( const char *uri, int create, int *save )
{
- epg_episode_t *ee;
- static epg_episode_t* skel = NULL;
-
- lock_assert(&global_lock); // pointless!
-
- if ( skel == NULL ) skel = calloc(1, sizeof(epg_episode_t));
- skel->ee_uri = (char*)id;
- skel->ee_id = _epg_episode_idx;
-
- /* Find */
- if ( !create ) {
- ee = RB_FIND(&epg_episodes, skel, ee_link, ee_uri_cmp);
-
- /* Create */
- } else {
- ee = RB_INSERT_SORTED(&epg_episodes, skel, ee_link, ee_uri_cmp);
- if ( ee == NULL ) {
- *save |= 1;
- ee = skel;
- skel = NULL;
- ee->ee_uri = strdup(id);
- _epg_episode_idx++;
- }
- }
-
- return ee;
+ return (epg_episode_t*)
+ _epg_object_find_by_uri(uri, create, save,
+ &epg_episodes, sizeof(epg_episode_t));
}
-epg_episode_t *epg_episode_find_by_id ( uint32_t id )
+epg_episode_t *epg_episode_find_by_id ( uint64_t id )
{
- epg_episode_t *ee;
- RB_FOREACH(ee, &epg_episodes, ee_link) {
- if ( ee->ee_id == id ) return ee;
- }
- return NULL;
+ return (epg_episode_t*)_epg_object_find_by_id(id, &epg_episodes);
}
int epg_episode_set_title ( epg_episode_t *episode, const char *title )
{
int save = 0;
if ( !episode || !title ) return 0;
- if ( !episode->ee_title || strcmp(episode->ee_title, title) ) {
- if ( episode->ee_title ) free(episode->ee_title);
- episode->ee_title = strdup(title);
+ if ( !episode->title || strcmp(episode->title, title) ) {
+ if ( episode->title ) free(episode->title);
+ episode->title = strdup(title);
save = 1;
}
return save;
@@ -751,9 +725,9 @@ int epg_episode_set_subtitle ( epg_episode_t *episode, const char *subtitle )
{
int save = 0;
if ( !episode || !subtitle ) return 0;
- if ( !episode->ee_subtitle || strcmp(episode->ee_subtitle, subtitle) ) {
- if ( episode->ee_subtitle ) free(episode->ee_subtitle);
- episode->ee_subtitle = strdup(subtitle);
+ if ( !episode->subtitle || strcmp(episode->subtitle, subtitle) ) {
+ if ( episode->subtitle ) free(episode->subtitle);
+ episode->subtitle = strdup(subtitle);
save = 1;
}
return save;
@@ -763,9 +737,9 @@ int epg_episode_set_summary ( epg_episode_t *episode, const char *summary )
{
int save = 0;
if ( !episode || !summary ) return 0;
- if ( !episode->ee_summary || strcmp(episode->ee_summary, summary) ) {
- if ( episode->ee_summary ) free(episode->ee_summary);
- episode->ee_summary = strdup(summary);
+ if ( !episode->summary || strcmp(episode->summary, summary) ) {
+ if ( episode->summary ) free(episode->summary);
+ episode->summary = strdup(summary);
save = 1;
}
return save;
@@ -775,9 +749,9 @@ int epg_episode_set_description ( epg_episode_t *episode, const char *desc )
{
int save = 0;
if ( !episode || !desc ) return 0;
- if ( !episode->ee_description || strcmp(episode->ee_description, desc) ) {
- if ( episode->ee_description ) free(episode->ee_description);
- episode->ee_description = strdup(desc);
+ if ( !episode->description || strcmp(episode->description, desc) ) {
+ if ( episode->description ) free(episode->description);
+ episode->description = strdup(desc);
save = 1;
}
return save;
@@ -787,8 +761,8 @@ int epg_episode_set_number ( epg_episode_t *episode, uint16_t number )
{
int save = 0;
if ( !episode || !number ) return 0;
- if ( episode->ee_number != number ) {
- episode->ee_number = number;
+ if ( episode->number != number ) {
+ episode->number = number;
save = 1;
}
return save;
@@ -799,12 +773,12 @@ int epg_episode_set_part ( epg_episode_t *episode, uint16_t part, uint16_t count
int save = 0;
// TODO: could treat part/count independently
if ( !episode || !part || !count ) return 0;
- if ( episode->ee_part_number != part ) {
- episode->ee_part_number = part;
+ if ( episode->part_number != part ) {
+ episode->part_number = part;
save |= 1;
}
- if ( episode->ee_part_count != count ) {
- episode->ee_part_count = count;
+ if ( episode->part_count != count ) {
+ episode->part_count = count;
save |= 1;
}
return save;
@@ -814,10 +788,10 @@ int epg_episode_set_brand ( epg_episode_t *episode, epg_brand_t *brand, int u )
{
int save = 0;
if ( !episode || !brand ) return 0;
- if ( episode->ee_brand != brand ) {
- if ( u ) save |= epg_brand_rem_episode(episode->ee_brand, episode, 0); /// does nothing
- episode->ee_brand = brand;
- if ( u ) save |= epg_brand_add_episode(episode->ee_brand, episode, 0);
+ if ( episode->brand != brand ) {
+ if ( u ) save |= epg_brand_rem_episode(episode->brand, episode, 0); /// does nothing
+ episode->brand = brand;
+ if ( u ) save |= epg_brand_add_episode(episode->brand, episode, 0);
save |= 1;
}
return save;
@@ -827,12 +801,12 @@ int epg_episode_set_season ( epg_episode_t *episode, epg_season_t *season, int u
{
int save = 0;
if ( !episode || !season ) return 0;
- if ( episode->ee_season != season ) {
- if ( u ) save |= epg_season_rem_episode(episode->ee_season, episode, 0);
- episode->ee_season = season;
- if ( u && episode->ee_season ) {
- save |= epg_season_add_episode(episode->ee_season, episode, 0);
- save |= epg_brand_add_episode(episode->ee_season->es_brand, episode, 0);
+ if ( episode->season != season ) {
+ if ( u ) save |= epg_season_rem_episode(episode->season, episode, 0);
+ episode->season = season;
+ if ( u && episode->season ) {
+ save |= epg_season_add_episode(episode->season, episode, 0);
+ save |= epg_brand_add_episode(episode->season->brand, episode, 0);
// TODO: is this the right place?
}
save = 1;
@@ -846,7 +820,7 @@ int epg_episode_add_broadcast
int save = 0;
epg_broadcast_t *eb;
if ( !episode || !broadcast ) return 0;
- eb = RB_INSERT_SORTED(&episode->ee_broadcasts, broadcast, eb_elink, ptr_cmp);
+ eb = RB_INSERT_SORTED(&episode->broadcasts, broadcast, elink, _ptr_cmp);
if ( eb == NULL ) {
if ( u ) save |= epg_broadcast_set_episode(broadcast, episode, 0);
save = 1;
@@ -860,10 +834,10 @@ int epg_episode_rem_broadcast
int save = 0;
epg_broadcast_t *eb;
if ( !episode || !broadcast ) return 0;
- eb = RB_FIND(&episode->ee_broadcasts, broadcast, eb_elink, ptr_cmp);
+ eb = RB_FIND(&episode->broadcasts, broadcast, elink, _ptr_cmp);
if ( eb != NULL ) {
if ( u ) save |= epg_broadcast_set_episode(broadcast, episode, 0);
- RB_REMOVE(&episode->ee_broadcasts, broadcast, eb_elink);
+ RB_REMOVE(&episode->broadcasts, broadcast, elink);
save = 1;
}
return save;
@@ -873,13 +847,13 @@ int epg_episode_get_number_onscreen
( epg_episode_t *episode, char *buf, int len )
{
int i = 0;
- if ( episode->ee_number ) {
+ if ( episode->number ) {
// TODO: add counts
- if ( episode->ee_season && episode->ee_season->es_number ) {
+ if ( episode->season && episode->season->number ) {
i += snprintf(&buf[i], len-i, "Season %d ",
- episode->ee_season->es_number);
+ episode->season->number);
}
- i += snprintf(&buf[i], len-i, "Episode %d", episode->ee_number);
+ i += snprintf(&buf[i], len-i, "Episode %d", episode->number);
}
return i;
}
@@ -887,27 +861,27 @@ int epg_episode_get_number_onscreen
htsmsg_t *epg_episode_serialize ( epg_episode_t *episode )
{
htsmsg_t *m;
- if (!episode || !episode->ee_uri) return NULL;
+ if (!episode || !episode->_.uri) return NULL;
m = htsmsg_create_map();
- htsmsg_add_str(m, "uri", episode->ee_uri);
- if (episode->ee_title)
- htsmsg_add_str(m, "title", episode->ee_title);
- if (episode->ee_subtitle)
- htsmsg_add_str(m, "subtitle", episode->ee_subtitle);
- if (episode->ee_summary)
- htsmsg_add_str(m, "summary", episode->ee_summary);
- if (episode->ee_description)
- htsmsg_add_str(m, "description", episode->ee_description);
- if (episode->ee_number)
- htsmsg_add_u32(m, "number", episode->ee_number);
- if (episode->ee_part_count && episode->ee_part_count) {
- htsmsg_add_u32(m, "part-number", episode->ee_part_number);
- htsmsg_add_u32(m, "part-count", episode->ee_part_count);
+ htsmsg_add_str(m, "uri", episode->_.uri);
+ if (episode->title)
+ htsmsg_add_str(m, "title", episode->title);
+ if (episode->subtitle)
+ htsmsg_add_str(m, "subtitle", episode->subtitle);
+ if (episode->summary)
+ htsmsg_add_str(m, "summary", episode->summary);
+ if (episode->description)
+ htsmsg_add_str(m, "description", episode->description);
+ if (episode->number)
+ htsmsg_add_u32(m, "number", episode->number);
+ if (episode->part_count && episode->part_count) {
+ htsmsg_add_u32(m, "part-number", episode->part_number);
+ htsmsg_add_u32(m, "part-count", episode->part_count);
}
- if (episode->ee_brand)
- htsmsg_add_str(m, "brand", episode->ee_brand->eb_uri);
- if (episode->ee_season)
- htsmsg_add_str(m, "season", episode->ee_season->es_uri);
+ if (episode->brand)
+ htsmsg_add_str(m, "brand", episode->brand->_.uri);
+ if (episode->season)
+ htsmsg_add_str(m, "season", episode->season->_.uri);
return m;
}
@@ -950,53 +924,31 @@ epg_episode_t *epg_episode_deserialize ( htsmsg_t *m, int create, int *save )
* Broadcast
* *************************************************************************/
-// one that starts at this time)
-//
-// Note: do we need to pass in stop?
epg_broadcast_t* epg_broadcast_find_by_time
( epg_channel_t *channel, time_t start, time_t stop, int create, int *save )
{
- epg_broadcast_t *eb;
- static epg_broadcast_t *skel = NULL;
-
+ static epg_broadcast_t *skel;
if ( !channel || !start || !stop ) return 0;
if ( stop < start ) return 0;
-
- lock_assert(&global_lock); // pointless!
if ( skel == NULL ) skel = calloc(1, sizeof(epg_broadcast_t));
- skel->eb_channel = channel;
- skel->eb_start = start;
- skel->eb_stop = stop;
- skel->eb_id = _epg_broadcast_idx;
-
- /* Find */
- if ( !create ) {
- eb = RB_FIND(&channel->ec_schedule, skel, eb_slink, ebc_win_cmp);
+ skel->channel = channel;
+ skel->start = start;
+ skel->stop = stop;
+ skel->_.id = _epg_object_idx; // TODO: prefer if this wasn't here!
- /* Create */
- } else {
- eb = RB_INSERT_SORTED(&channel->ec_schedule, skel, eb_slink, ebc_win_cmp);
- if ( eb == NULL ) {
- *save |= 1;
- eb = skel;
- skel = NULL;
- _epg_broadcast_idx++;
- }
- }
-
- return eb;
+ return (epg_broadcast_t*)
+ _epg_object_find(create, save, &channel->schedule,
+ (epg_object_t*)skel, _ebc_win_cmp);
}
// TODO: optional channel?
-epg_broadcast_t *epg_broadcast_find_by_id ( uint32_t id )
+epg_broadcast_t *epg_broadcast_find_by_id ( uint64_t id )
{
- epg_channel_t *ec;
- epg_broadcast_t *ebc;
- RB_FOREACH(ec, &epg_channels, ec_link) {
- RB_FOREACH(ebc, &ec->ec_schedule, eb_slink) {
- if (ebc->eb_id == id) return ebc;
- }
+ epg_object_t *eo, *ec;
+ RB_FOREACH(ec, &epg_channels, glink) {
+ eo = _epg_object_find_by_id(id, &((epg_channel_t*)ec)->schedule);
+ if (eo) return (epg_broadcast_t*)eo;
}
return NULL;
}
@@ -1006,8 +958,8 @@ int epg_broadcast_set_episode
{
int save = 0;
if ( !broadcast || !episode ) return 0;
- if ( broadcast->eb_episode != episode ) {
- broadcast->eb_episode = episode;
+ if ( broadcast->episode != episode ) {
+ broadcast->episode = episode;
if ( u ) save |= epg_episode_add_broadcast(episode, broadcast, 0);
save = 1;
}
@@ -1017,26 +969,26 @@ int epg_broadcast_set_episode
epg_broadcast_t *epg_broadcast_get_next ( epg_broadcast_t *broadcast )
{
if ( !broadcast ) return NULL;
- return RB_NEXT(broadcast, eb_slink);
+ return RB_NEXT(broadcast, slink);
}
htsmsg_t *epg_broadcast_serialize ( epg_broadcast_t *broadcast )
{
htsmsg_t *m;
if (!broadcast) return NULL;
- if (!broadcast->eb_channel || !broadcast->eb_channel->ec_uri) return NULL;
- if (!broadcast->eb_episode || !broadcast->eb_episode->ee_uri) return NULL;
+ if (!broadcast->channel || !broadcast->channel->_.uri) return NULL;
+ if (!broadcast->episode || !broadcast->episode->_.uri) return NULL;
m = htsmsg_create_map();
- htsmsg_add_u32(m, "id", broadcast->eb_id);
- htsmsg_add_u32(m, "start", broadcast->eb_start);
- htsmsg_add_u32(m, "stop", broadcast->eb_stop);
+ htsmsg_add_u32(m, "id", broadcast->_.id);
+ htsmsg_add_u32(m, "start", broadcast->start);
+ htsmsg_add_u32(m, "stop", broadcast->stop);
// TODO: should these be optional?
- htsmsg_add_str(m, "channel", broadcast->eb_channel->ec_uri);
- htsmsg_add_str(m, "episode", broadcast->eb_episode->ee_uri);
+ htsmsg_add_str(m, "channel", broadcast->channel->_.uri);
+ htsmsg_add_str(m, "episode", broadcast->episode->_.uri);
- if (broadcast->eb_dvb_id)
- htsmsg_add_u32(m, "dvb-id", broadcast->eb_dvb_id);
+ if (broadcast->dvb_id)
+ htsmsg_add_u32(m, "dvb-id", broadcast->dvb_id);
// TODO: add other metadata fields
return m;
}
@@ -1048,9 +1000,10 @@ epg_broadcast_t *epg_broadcast_deserialize
epg_channel_t *ec;
epg_episode_t *ee;
const char *str;
- uint32_t id, start, stop;
+ uint32_t start, stop;
+ uint64_t id;
- if ( htsmsg_get_u32(m, "id", &id) ) return NULL;
+ if ( htsmsg_get_u64(m, "id", &id) ) return NULL;
if ( htsmsg_get_u32(m, "start", &start) ) return NULL;
if ( htsmsg_get_u32(m, "stop", &stop) ) return NULL;
// TODO: should these be optional?
@@ -1065,8 +1018,8 @@ epg_broadcast_t *epg_broadcast_deserialize
*save |= epg_broadcast_set_episode(ebc, ee, 1);
/* Bodge the ID - keep them the same */
- ebc->eb_id = id;
- if ( id >= _epg_broadcast_idx ) _epg_broadcast_idx = id + 1;
+ ebc->_.id = id;
+ if ( id >= _epg_object_idx ) _epg_object_idx = id + 1;
#if TODO_BROADCAST_METADATA
if ( !htsmsg_get_u32(m, "dvb-id", &u32) )
@@ -1082,44 +1035,16 @@ epg_broadcast_t *epg_broadcast_deserialize
* *************************************************************************/
epg_channel_t* epg_channel_find_by_uri
- ( const char *id, int create, int *save )
+ ( const char *uri, int create, int *save )
{
- epg_channel_t *ec;
- static epg_channel_t *skel = NULL;
-
- lock_assert(&global_lock); // pointless!
-
- if ( skel == NULL ) skel = calloc(1, sizeof(epg_channel_t));
- skel->ec_uri = (char*)id;
- skel->ec_id = _epg_channel_idx;
-
- /* Find */
- if ( !create ) {
- ec = RB_FIND(&epg_channels, skel, ec_link, ec_uri_cmp);
-
- /* Create */
- } else {
- ec = RB_INSERT_SORTED(&epg_channels, skel, ec_link, ec_uri_cmp);
- if ( ec == NULL ) {
- *save |= 1;
- ec = skel;
- skel = NULL;
- ec->ec_uri = strdup(id);
- LIST_INSERT_HEAD(&epg_unlinked_channels1, ec, ec_ulink);
- _epg_channel_idx++;
- }
- }
-
- return ec;
+ return (epg_channel_t*)
+ _epg_object_find_by_uri(uri, create, save,
+ &epg_channels, sizeof(epg_channel_t));
}
-epg_channel_t *epg_channel_find_by_id ( uint32_t id )
+epg_channel_t *epg_channel_find_by_id ( uint64_t id )
{
- epg_channel_t *ec;
- RB_FOREACH(ec, &epg_channels, ec_link) {
- if (ec->ec_id == id) return ec;
- }
- return NULL;
+ return (epg_channel_t*)_epg_object_find_by_id(id, &epg_channels);
}
int epg_channel_set_name ( epg_channel_t *channel, const char *name )
@@ -1127,9 +1052,9 @@ int epg_channel_set_name ( epg_channel_t *channel, const char *name )
int save = 0;
channel_t *ch;
if ( !channel || !name ) return 0;
- if ( !channel->ec_name || strcmp(channel->ec_name, name) ) {
- channel->ec_name = strdup(name);
- if ( !channel->ec_channel ) {
+ if ( !channel->name || strcmp(channel->name, name) ) {
+ channel->name = strdup(name);
+ if ( !channel->channel ) {
LIST_FOREACH(ch, &epg_unlinked_channels2, ch_eulink) {
if ( _epg_channel_match(channel, ch) ) {
epg_channel_set_channel(channel, ch);
@@ -1146,17 +1071,19 @@ int epg_channel_set_name ( epg_channel_t *channel, const char *name )
int epg_channel_set_channel ( epg_channel_t *ec, channel_t *ch )
{
int save = 0;
+#if TODO_REDO_CHANNEL_LINKING
if ( !ec || !ch ) return 0;
- if ( ec->ec_channel != ch ) {
- if (!ec->ec_channel) LIST_REMOVE(ec, ec_ulink);
+ if ( ec->channel != ch ) {
+ if (!ec->channel) LIST_REMOVE(ec, ulink);
if (!ch->ch_epg_channel) LIST_REMOVE(ch, ch_eulink);
// TODO: should it be possible to "change" it
- //if(ec->ec_channel)
- // channel_set_epg_source(ec->ec_channel, NULL)
- // LIST_INSERT_HEAD(&epg_unlinked_channels2, ec->ec_channel, ch_eulink);
- ec->ec_channel = ch;
+ //if(ec->channel)
+ // channel_set_epg_source(ec->channel, NULL)
+ // LIST_INSERT_HEAD(&epg_unlinked_channels2, ec->channel, ch_eulink);
+ ec->channel = ch;
channel_set_epg_source(ch, ec);
}
+#endif
return save;
}
@@ -1164,19 +1091,19 @@ epg_broadcast_t *epg_channel_get_current_broadcast ( epg_channel_t *channel )
{
// TODO: its not really the head!
if ( !channel ) return NULL;
- return RB_FIRST(&channel->ec_schedule);
+ return (epg_broadcast_t*)RB_FIRST(&channel->schedule);
}
htsmsg_t *epg_channel_serialize ( epg_channel_t *channel )
{
htsmsg_t *m;
- if (!channel || !channel->ec_uri) return NULL;
+ if (!channel || !channel->_.uri) return NULL;
m = htsmsg_create_map();
- htsmsg_add_str(m, "uri", channel->ec_uri);
- if (channel->ec_name)
- htsmsg_add_str(m, "name", channel->ec_name);
- if (channel->ec_channel)
- htsmsg_add_u32(m, "channel", channel->ec_channel->ch_id);
+ htsmsg_add_str(m, "uri", channel->_.uri);
+ if (channel->name)
+ htsmsg_add_str(m, "name", channel->name);
+ if (channel->channel)
+ htsmsg_add_u32(m, "channel", channel->channel->ch_id);
// TODO: other data
return m;
}
@@ -1223,10 +1150,11 @@ static void _eqr_add ( epg_query_result_t *eqr, epg_broadcast_t *e )
static void _eqr_add_channel
( epg_query_result_t *eqr, epg_channel_t *ec )
{
- // TODO: add other searching
+ epg_object_t *eo;
epg_broadcast_t *ebc;
- RB_FOREACH(ebc, &ec->ec_schedule, eb_slink) {
- if ( ebc->eb_episode && ebc->eb_channel ) _eqr_add(eqr, ebc);
+ RB_FOREACH(eo, &ec->schedule, glink) {
+ ebc = (epg_broadcast_t*)eo;
+ if ( ebc->episode && ebc->channel ) _eqr_add(eqr, ebc);
}
}
@@ -1234,15 +1162,15 @@ void epg_query0
( epg_query_result_t *eqr, channel_t *channel, channel_tag_t *tag,
uint8_t contentgroup, const char *title )
{
- epg_channel_t *ec;
+ epg_object_t *ec;
/* Clear (just incase) */
memset(eqr, 0, sizeof(epg_query_result_t));
/* All channels */
if (!channel) {
- RB_FOREACH(ec, &epg_channels, ec_link) {
- _eqr_add_channel(eqr, ec);
+ RB_FOREACH(ec, &epg_channels, glink) {
+ _eqr_add_channel(eqr, (epg_channel_t*)ec);
}
/* Single channel */
@@ -1269,7 +1197,7 @@ void epg_query_free(epg_query_result_t *eqr)
static int _epg_sort_start_ascending ( const void *a, const void *b )
{
- return (*(epg_broadcast_t**)a)->eb_start - (*(epg_broadcast_t**)b)->eb_start;
+ return (*(epg_broadcast_t**)a)->start - (*(epg_broadcast_t**)b)->start;
}
void epg_query_sort(epg_query_result_t *eqr)
diff --git a/src/epg.h b/src/epg.h
index 4fb9e860..297c15a7 100644
--- a/src/epg.h
+++ b/src/epg.h
@@ -32,6 +32,7 @@
/*
* Map types
*/
+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);
@@ -39,13 +40,40 @@ RB_HEAD(epg_channel_tree, epg_channel);
RB_HEAD(epg_broadcast_tree, epg_broadcast);
/*
- * Forward declerations
+ * Typedefs
*/
-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 epg_object_t;
+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_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;
+
+/* ************************************************************************
+ * Generic Object
+ * ***********************************************************************/
+
+/* Object */
+typedef struct epg_object
+{
+ RB_ENTRY(epg_object) glink; ///< Global list link
+ RB_ENTRY(epg_object) ulink; ///< Global unref'd link
+
+ char *uri; ///< Unique ID (from grabber)
+ uint64_t id; ///< Internal ID
+ int refcount; ///< Reference counting
+
+ void (*getref) ( epg_object_t* ); ///< Get a reference
+ void (*putref) ( epg_object_t* ); ///< Release a reference
+ void (*destroy) ( epg_object_t* ); ///< Delete the object
+} epg_object_t;
+
/* ************************************************************************
* Brand - Represents a specific show
@@ -55,24 +83,20 @@ typedef struct epg_channel epg_channel_t;
/* Object */
typedef struct epg_brand
{
- RB_ENTRY(epg_brand) eb_link; ///< Global list link
+ epg_object_t _; ///< Base object
- uint32_t eb_id; ///< Internal ID
- char *eb_uri; ///< Grabber URI
- char *eb_title; ///< Brand name
- char *eb_summary; ///< Brand summary
- uint16_t eb_season_count; ///< Total number of seasons
+ char *title; ///< Brand name
+ char *summary; ///< Brand summary
+ uint16_t season_count; ///< Total number of seasons
- struct epg_season_tree eb_seasons; ///< Season list
- struct epg_episode_tree eb_episodes; ///< Episode list
-
- int eb_refcount; ///< Reference counting
+ epg_season_tree_t seasons; ///< Season list
+ epg_episode_tree_t episodes; ///< Episode list
} epg_brand_t;
/* Lookup */
epg_brand_t *epg_brand_find_by_uri
( const char *uri, int create, int *save );
-epg_brand_t *epg_brand_find_by_id ( uint32_t id );
+epg_brand_t *epg_brand_find_by_id ( uint64_t id );
/* Mutators */
int epg_brand_set_title ( epg_brand_t *b, const char *title )
@@ -101,26 +125,22 @@ epg_brand_t *epg_brand_deserialize ( htsmsg_t *m, int create, int *save );
/* Object */
typedef struct epg_season
{
- RB_ENTRY(epg_season) es_link; ///< Global list link
- RB_ENTRY(epg_season) es_blink; ///< Brand list link
+ epg_object_t _; ///< Parent object
- uint32_t es_id; ///< Internal ID
- char *es_uri; ///< Grabber URI
- char *es_summary; ///< Season summary
- uint16_t es_number; ///< The season number
- uint16_t es_episode_count; ///< Total number of episodes
+ char *summary; ///< Season summary
+ uint16_t number; ///< The season number
+ uint16_t episode_count; ///< Total number of episodes
- epg_brand_t *es_brand; ///< Parent brand
- struct epg_episode_tree es_episodes; ///< Episode list
-
- int es_refcount; ///< Reference counting
+ RB_ENTRY(epg_season) blink; ///< Brand list link
+ epg_brand_t *brand; ///< Parent brand
+ epg_episode_tree_t episodes; ///< Episode list
} epg_season_t;
/* Lookup */
epg_season_t *epg_season_find_by_uri
( const char *uri, int create, int *save );
-epg_season_t *epg_season_find_by_id ( uint32_t id );
+epg_season_t *epg_season_find_by_id ( uint64_t id );
/* Mutators */
int epg_season_set_summary ( epg_season_t *s, const char *summary )
@@ -149,32 +169,29 @@ epg_season_t *epg_season_deserialize ( htsmsg_t *m, int create, int *save );
/* Object */
typedef struct epg_episode
{
- RB_ENTRY(epg_episode) ee_link; ///< Global link
- RB_ENTRY(epg_episode) ee_blink; ///< Brand link
- RB_ENTRY(epg_episode) ee_slink; ///< Season link
+ epg_object_t _; ///< Parent object
- uint32_t ee_id; ///< Internal ID
- char *ee_uri; ///< Grabber URI
- char *ee_title; ///< Title
- char *ee_subtitle; ///< Sub-title
- char *ee_summary; ///< Summary
- char *ee_description; ///< An extended description
- uint8_t ee_genre; ///< Episode genre
- uint16_t ee_number; ///< The episode number
- uint16_t ee_part_number; ///< For multipart episodes
- uint16_t ee_part_count; ///< For multipart episodes
+ char *title; ///< Title
+ char *subtitle; ///< Sub-title
+ char *summary; ///< Summary
+ char *description; ///< An extended description
+ uint8_t genre; ///< Episode genre
+ uint16_t number; ///< The episode number
+ uint16_t part_number; ///< For multipart episodes
+ uint16_t part_count; ///< For multipart episodes
- epg_brand_t *ee_brand; ///< (Grand-)Parent brand
- epg_season_t *ee_season; ///< Parent season
- struct epg_broadcast_tree ee_broadcasts; ///< Broadcast list
+ RB_ENTRY(epg_episode) blink; ///< Brand link
+ RB_ENTRY(epg_episode) slink; ///< Season link
+ epg_brand_t *brand; ///< (Grand-)Parent brand
+ epg_season_t *season; ///< Parent season
+ epg_broadcast_tree_t broadcasts; ///< Broadcast list
- int ee_refcount; ///< Reference counting
} epg_episode_t;
/* Lookup */
epg_episode_t *epg_episode_find_by_uri
( const char *uri, int create, int *save );
-epg_episode_t *epg_episode_find_by_id ( uint32_t id );
+epg_episode_t *epg_episode_find_by_id ( uint64_t id );
/* Mutators */
int epg_episode_set_title ( epg_episode_t *e, const char *title )
@@ -213,39 +230,38 @@ epg_episode_t *epg_episode_deserialize ( htsmsg_t *m, int create, int *save );
/* Object */
typedef struct epg_broadcast
{
- RB_ENTRY(epg_broadcast) eb_slink; ///< Schedule link
- RB_ENTRY(epg_broadcast) eb_elink; ///< Episode link
-
- uint32_t eb_id; ///< Internal ID
- uint32_t eb_dvb_id; ///< DVB identifier
- time_t eb_start; ///< Start time
- time_t eb_stop; ///< End time
+ epg_object_t _; ///< Parent object
+
+ uint32_t dvb_id; ///< DVB identifier
+ time_t start; ///< Start time
+ time_t stop; ///< End time
/* Some quality info */
- uint8_t eb_widescreen; ///< Is widescreen
- uint8_t eb_hd; ///< Is HD
- uint16_t eb_lines; ///< Lines in image (quality)
- uint16_t eb_aspect; ///< Aspect ratio (*100)
+ 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)
/* Some accessibility support */
- uint8_t eb_deafsigned; ///< In screen signing
- uint8_t eb_subtitled; ///< Teletext subtitles
- uint8_t eb_audio_desc; ///< Audio description
+ uint8_t is_deafsigned; ///< In screen signing
+ uint8_t is_subtitled; ///< Teletext subtitles
+ uint8_t is_audio_desc; ///< Audio description
/* Misc flags */
- uint8_t eb_new; ///< New series / file premiere
- uint8_t eb_repeat; ///< Repeat screening
+ uint8_t is_new; ///< New series / file premiere
+ uint8_t is_repeat; ///< Repeat screening
- epg_episode_t *eb_episode; ///< Episode shown
- epg_channel_t *eb_channel; ///< Channel being broadcast on
+ RB_ENTRY(epg_broadcast) slink; ///< Schedule link
+ RB_ENTRY(epg_broadcast) elink; ///< Episode link
+ epg_episode_t *episode; ///< Episode shown
+ epg_channel_t *channel; ///< Channel being broadcast on
- int eb_refcount; ///< Reference counting
} 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 ( uint32_t id );
+epg_broadcast_t *epg_broadcast_find_by_id ( uint64_t id );
/* Mutators */
int epg_broadcast_set_episode ( epg_broadcast_t *b, epg_episode_t *e, int u )
@@ -266,25 +282,20 @@ epg_broadcast_t *epg_broadcast_deserialize
/* Object */
typedef struct epg_channel
{
- RB_ENTRY(epg_channel) ec_link; ///< Global link
+ epg_object_t _; ///< Parent object
- uint32_t ec_id; ///< Internal ID
- char *ec_uri; ///< Grabber URI
- char *ec_name; ///< Channel name
- char **ec_sname; ///< DVB svc names (to map)
- int **ec_sid; ///< DVB svc ids (to map)
+ char *name; ///< Channel name
+ char **sname; ///< DVB svc names (to map)
+ int **sid; ///< DVB svc ids (to map)
- channel_t *ec_channel; ///< Link to real channel
- LIST_ENTRY(epg_channel) ec_ulink; ///< Unlinked list
-
- struct epg_broadcast_tree ec_schedule; ///< Schedule (broadcasts)
-
+ channel_t *channel; ///< Link to real channel
+ epg_object_tree_t schedule; ///< Schedule (broadcasts)
} 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 ( uint32_t id );
+epg_channel_t *epg_channel_find_by_id ( uint64_t id );
/* Mutators */
int epg_channel_set_name ( epg_channel_t *c, const char *n )
diff --git a/src/htsp.c b/src/htsp.c
index 3fee181b..abfb147c 100644
--- a/src/htsp.c
+++ b/src/htsp.c
@@ -312,8 +312,8 @@ htsp_build_channel(channel_t *ch, const char *method)
now = epg_channel_get_current_broadcast(ch->ch_epg_channel);
if ( now ) next = epg_broadcast_get_next(now);
- htsmsg_add_u32(out, "eventId", now ? now->eb_id : 0);
- htsmsg_add_u32(out, "nextEventId", next ? next->eb_id : 0);
+ 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;
@@ -730,7 +730,7 @@ htsp_method_epgQuery(htsp_connection_t *htsp, htsmsg_t *in)
if( c ) {
eventIds = htsmsg_create_list();
for(i = 0; i < c; ++i) {
- htsmsg_add_u32(eventIds, NULL, eqr.eqr_array[i]->eb_id);
+ htsmsg_add_u32(eventIds, NULL, eqr.eqr_array[i]->_.id);
}
htsmsg_add_msg(out, "eventIds", eventIds);
}
@@ -754,18 +754,18 @@ htsp_build_event(epg_broadcast_t *e)
out = htsmsg_create_map();
- htsmsg_add_u32(out, "eventId", e->eb_id);
+ htsmsg_add_u32(out, "eventId", e->_.id);
#if TODO_EPG_CHANNEL
htsmsg_add_u32(out, "channelId", e->e_channel->ch_id);
#endif
- htsmsg_add_u32(out, "start", e->eb_start);
- htsmsg_add_u32(out, "stop", e->eb_stop);
- if(e->eb_episode->ee_title != NULL)
- htsmsg_add_str(out, "title", e->eb_episode->ee_title);
- if(e->eb_episode->ee_description != NULL)
- htsmsg_add_str(out, "description", e->eb_episode->ee_description);
- else if(e->eb_episode->ee_summary != NULL)
- htsmsg_add_str(out, "description", e->eb_episode->ee_summary);
+ htsmsg_add_u32(out, "start", e->start);
+ htsmsg_add_u32(out, "stop", e->stop);
+ if(e->episode->title != NULL)
+ htsmsg_add_str(out, "title", e->episode->title);
+ if(e->episode->description != NULL)
+ htsmsg_add_str(out, "description", e->episode->description);
+ else if(e->episode->summary != NULL)
+ htsmsg_add_str(out, "description", e->episode->summary);
#if TODO_REMOVE_THESE
if(e->e_ext_desc != NULL)
htsmsg_add_str(out, "ext_desc", e->e_ext_desc);
@@ -775,8 +775,8 @@ htsp_build_event(epg_broadcast_t *e)
htsmsg_add_str(out, "ext_text", e->e_ext_text);
#endif
- if(e->eb_episode->ee_genre)
- htsmsg_add_u32(out, "contentType", e->eb_episode->ee_genre);
+ if(e->episode->genre)
+ htsmsg_add_u32(out, "contentType", e->episode->genre);
#if TODO_DVR
if((de = dvr_entry_find_by_event(e)) != NULL) {
@@ -786,7 +786,7 @@ htsp_build_event(epg_broadcast_t *e)
n = epg_broadcast_get_next(e);
if(n != NULL)
- htsmsg_add_u32(out, "nextEventId", n->eb_id);
+ htsmsg_add_u32(out, "nextEventId", n->_.id);
return out;
}
@@ -1427,8 +1427,8 @@ htsp_channel_update_current(channel_t *ch)
now = epg_channel_get_current_broadcast(ch->ch_epg_channel);
next = epg_broadcast_get_next(now);
- htsmsg_add_u32(m, "eventId", now ? now->eb_id : 0);
- htsmsg_add_u32(m, "nextEventId", next ? next->eb_id : 0);
+ 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 d25574b7..a7116c59 100644
--- a/src/webui/extjs.c
+++ b/src/webui/extjs.c
@@ -709,8 +709,8 @@ extjs_epg(http_connection_t *hc, const char *remain, void *opaque)
for(i = start; i < end; i++) {
e = eqr.eqr_array[i];
- ee = e->eb_episode;
- ch = e->eb_channel->ec_channel;
+ ee = e->episode;
+ ch = e->channel->channel;
if (!ch||!ee) continue;
m = htsmsg_create_map();
@@ -720,13 +720,13 @@ extjs_epg(http_connection_t *hc, const char *remain, void *opaque)
if(ch->ch_icon != NULL)
htsmsg_add_str(m, "chicon", ch->ch_icon);
- if(ee->ee_title != NULL)
- htsmsg_add_str(m, "title", ee->ee_title);
+ if(ee->title != NULL)
+ htsmsg_add_str(m, "title", ee->title);
- if(ee->ee_description != NULL)
- htsmsg_add_str(m, "description", ee->ee_description);
- else if(ee->ee_summary != NULL)
- htsmsg_add_str(m, "description", ee->ee_summary);
+ if(ee->description != NULL)
+ htsmsg_add_str(m, "description", ee->description);
+ else if(ee->summary != NULL)
+ htsmsg_add_str(m, "description", ee->summary);
if (epg_episode_get_number_onscreen(ee, buf, 100))
htsmsg_add_str(m, "episode", strdup(buf));
@@ -742,10 +742,10 @@ extjs_epg(http_connection_t *hc, const char *remain, void *opaque)
htsmsg_add_str(m, "ext_text", e->e_ext_text);
#endif
- htsmsg_add_u32(m, "id", e->eb_id);
- htsmsg_add_u32(m, "start", e->eb_start);
- htsmsg_add_u32(m, "end", e->eb_stop);
- htsmsg_add_u32(m, "duration", e->eb_stop - e->eb_start);
+ htsmsg_add_u32(m, "id", e->_.id);
+ htsmsg_add_u32(m, "start", e->start);
+ htsmsg_add_u32(m, "end", e->stop);
+ htsmsg_add_u32(m, "duration", e->stop - e->start);
#if TODO_INCLUDE_GENRE_SUPORT
if((s = epg_content_group_get_name(e->e_content_type)) != NULL)
@@ -794,49 +794,49 @@ extjs_epgrelated(http_connection_t *hc, const char *remain, void *opaque)
pthread_mutex_lock(&global_lock);
if ( id && type ) {
e = epg_broadcast_find_by_id(atoi(id));
- if ( e && e->eb_episode ) {
- ee = e->eb_episode;
+ if ( e && e->episode ) {
+ ee = e->episode;
/* Alternative broadcasts */
if (!strcmp(type, "alternative")) {
- RB_FOREACH(ebc, &ee->ee_broadcasts, eb_elink) {
- ch = ebc->eb_channel->ec_channel;
+ RB_FOREACH(ebc, &ee->broadcasts, elink) {
+ ch = ebc->channel->channel;
if ( !ch ) continue; // skip something not viewable
if ( ebc == e ) continue; // skip self
count++;
m = htsmsg_create_map();
- htsmsg_add_u32(m, "id", ebc->eb_id);
+ htsmsg_add_u32(m, "id", ebc->_.id);
if ( ch->ch_name ) htsmsg_add_str(m, "channel", ch->ch_name);
if ( ch->ch_icon ) htsmsg_add_str(m, "chicon", ch->ch_icon);
- htsmsg_add_u32(m, "start", ebc->eb_start);
+ htsmsg_add_u32(m, "start", ebc->start);
htsmsg_add_msg(array, NULL, m);
}
/* Related */
} else if (!strcmp(type, "related")) {
// TODO: broadcasts?
- if (ee->ee_brand) {
- RB_FOREACH(ee2, &ee->ee_brand->eb_episodes, ee_blink) {
+ if (ee->brand) {
+ RB_FOREACH(ee2, &ee->brand->episodes, blink) {
if (ee2 == ee) continue;
- if (!ee2->ee_title) continue;
+ if (!ee2->title) continue;
count++;
m = htsmsg_create_map();
- htsmsg_add_str(m, "uri", ee2->ee_uri);
- htsmsg_add_str(m, "title", ee2->ee_title);
- if (ee2->ee_subtitle) htsmsg_add_str(m, "title", ee2->ee_subtitle);
+ htsmsg_add_str(m, "uri", ee2->_.uri);
+ htsmsg_add_str(m, "title", ee2->title);
+ if (ee2->subtitle) htsmsg_add_str(m, "title", ee2->subtitle);
if (epg_episode_get_number_onscreen(ee2, buf, 100))
htsmsg_add_str(m, "episode", strdup(buf));
htsmsg_add_msg(array, NULL, m);
}
- } else if (ee->ee_season) {
- RB_FOREACH(ee2, &ee->ee_season->es_episodes, ee_slink) {
+ } else if (ee->season) {
+ RB_FOREACH(ee2, &ee->season->episodes, slink) {
if (ee2 == ee) continue;
- if (!ee2->ee_title) continue;
+ if (!ee2->title) continue;
count++;
m = htsmsg_create_map();
- htsmsg_add_str(m, "uri", ee2->ee_uri);
- htsmsg_add_str(m, "title", ee2->ee_title);
- if (ee2->ee_subtitle) htsmsg_add_str(m, "title", ee2->ee_subtitle);
+ htsmsg_add_str(m, "uri", ee2->_.uri);
+ htsmsg_add_str(m, "title", ee2->title);
+ if (ee2->subtitle) htsmsg_add_str(m, "title", ee2->subtitle);
if (epg_episode_get_number_onscreen(ee2, buf, 100))
htsmsg_add_str(m, "episode", strdup(buf));
htsmsg_add_msg(array, NULL, m);
@@ -1175,8 +1175,8 @@ extjs_dvrlist(http_connection_t *hc, const char *remain, void *opaque)
htsmsg_add_str(m, "description", de->de_desc);
#if TODO_DVR
- if(de->de_episode.ee_onscreen)
- htsmsg_add_str(m, "episode", de->de_episode.ee_onscreen);
+ if(de->de_episode.onscreen)
+ htsmsg_add_str(m, "episode", de->de_episode.onscreen);
#endif
htsmsg_add_u32(m, "id", de->de_id);
diff --git a/src/webui/simpleui.c b/src/webui/simpleui.c
index d4f34b8c..d96b3f92 100644
--- a/src/webui/simpleui.c
+++ b/src/webui/simpleui.c
@@ -108,8 +108,8 @@ page_simple(http_connection_t *hc,
for(k = 0; k < c; k++) {
e = eqr.eqr_array[k];
- localtime_r(&e->eb_start, &a);
- localtime_r(&e->eb_stop, &b);
+ localtime_r(&e->start, &a);
+ localtime_r(&e->stop, &b);
if(a.tm_wday != day.tm_wday || a.tm_mday != day.tm_mday ||
a.tm_mon != day.tm_mon || a.tm_year != day.tm_year) {
@@ -128,9 +128,9 @@ page_simple(http_connection_t *hc,
htsbuf_qprintf(hq,
""
"%02d:%02d-%02d:%02d %s%s%s
",
- e->eb_id,
+ e->_.id,
a.tm_hour, a.tm_min, b.tm_hour, b.tm_min,
- e->eb_episode->ee_title,
+ e->episode->title,
rstatus ? " " : "", rstatus ?: "");
}
}
@@ -223,8 +223,8 @@ page_einfo(http_connection_t *hc, const char *remain, void *opaque)
htsbuf_qprintf(hq, "");
htsbuf_qprintf(hq, "