Reviewed teh EPG code, simplfied a few areas and found at least one possible bug resulting in extra reference counts on broadcasts that have extended in time (fairly rare event).

This commit is contained in:
Adam Sutton 2012-07-05 15:15:51 +01:00
parent cb5c20b8be
commit 83701298fa
2 changed files with 151 additions and 203 deletions

346
src/epg.c
View file

@ -116,7 +116,7 @@ void epg_updated ( void )
}
/* **************************************************************************
* Object
* Object (Generic routines)
* *************************************************************************/
static void _epg_object_destroy
@ -129,30 +129,33 @@ static void _epg_object_destroy
LIST_REMOVE(eo, id_link);
}
static void _epg_object_getref ( epg_object_t *eo )
static void _epg_object_getref ( void *o )
{
epg_object_t *eo = o;
if (eo->refcount == 0) LIST_REMOVE(eo, un_link);
eo->refcount++;
}
static void _epg_object_putref ( epg_object_t *eo )
static void _epg_object_putref ( void *o )
{
epg_object_t *eo = o;
assert(eo->refcount>0);
eo->refcount--;
if (!eo->refcount) eo->destroy(eo);
}
static void _epg_object_set_updated ( void *p )
static void _epg_object_set_updated ( void *o )
{
epg_object_t *eo = (epg_object_t*)p;
epg_object_t *eo = (epg_object_t*)o;
if (!eo->_updated) {
eo->_updated = 1;
LIST_INSERT_HEAD(&epg_object_updated, eo, up_link);
}
}
static void _epg_object_create ( epg_object_t *eo )
static void _epg_object_create ( void *o )
{
epg_object_t *eo = o;
if (!eo->id) eo->id = ++_epg_object_idx;
else if (eo->id > _epg_object_idx) _epg_object_idx = eo->id;
if (!eo->getref) eo->getref = _epg_object_getref;
@ -200,8 +203,9 @@ static epg_object_t *_epg_object_find_by_id ( uint64_t id, epg_object_type_t typ
return NULL;
}
static htsmsg_t * _epg_object_serialize ( epg_object_t *eo )
static htsmsg_t * _epg_object_serialize ( void *o )
{
epg_object_t *eo = o;
htsmsg_t *m;
if ( !eo->id || !eo->type ) return NULL;
m = htsmsg_create_map();
@ -263,7 +267,7 @@ static int _epg_object_set_u16
* Brand
* *************************************************************************/
static void _epg_brand_destroy ( epg_object_t *eo )
static void _epg_brand_destroy ( void *eo )
{
epg_brand_t *eb = (epg_brand_t*)eo;
if (LIST_FIRST(&eb->seasons)) {
@ -281,9 +285,9 @@ static void _epg_brand_destroy ( epg_object_t *eo )
free(eb);
}
static void _epg_brand_updated ( epg_object_t *eo )
static void _epg_brand_updated ( void *o )
{
dvr_autorec_check_brand((epg_brand_t*)eo);
dvr_autorec_check_brand((epg_brand_t*)o);
}
static epg_object_t **_epg_brand_skel ( void )
@ -314,64 +318,65 @@ epg_brand_t *epg_brand_find_by_id ( uint64_t id )
int epg_brand_set_title ( epg_brand_t *brand, const char *title )
{
if (!brand || !title) return 0;
return _epg_object_set_str(brand, &brand->title, title);
}
int epg_brand_set_summary ( epg_brand_t *brand, const char *summary )
{
if (!brand || !summary) return 0;
return _epg_object_set_str(brand, &brand->summary, summary);
}
int epg_brand_set_image ( epg_brand_t *brand, const char *image )
{
if (!brand || !image) return 0;
return _epg_object_set_str(brand, &brand->image, image);
}
int epg_brand_set_season_count ( epg_brand_t *brand, uint16_t count )
{
int save = 0;
if ( !brand || !count ) return 0;
if ( brand->season_count != count ) {
brand->season_count = count;
_epg_object_set_updated((epg_object_t*)brand);
save = 1;
}
return save;
if (!brand || !count) return 0;
return _epg_object_set_u16(brand, &brand->season_count, count);
}
static void _epg_brand_add_season
( epg_brand_t *brand, epg_season_t *season )
{
LIST_INSERT_SORTED(&brand->seasons, season, blink, _season_order);
_epg_object_set_updated((epg_object_t*)brand);
_epg_object_getref(brand);
_epg_object_set_updated(brand);
}
static void _epg_brand_rem_season
( epg_brand_t *brand, epg_season_t *season )
{
LIST_REMOVE(season, blink);
_epg_object_set_updated((epg_object_t*)brand);
_epg_object_putref(brand);
_epg_object_set_updated(brand);
}
static void _epg_brand_add_episode
( epg_brand_t *brand, epg_episode_t *episode )
{
LIST_INSERT_SORTED(&brand->episodes, episode, blink, _episode_order);
_epg_object_set_updated((epg_object_t*)brand);
_epg_object_getref(brand);
_epg_object_set_updated(brand);
}
static void _epg_brand_rem_episode
( epg_brand_t *brand, epg_episode_t *episode )
{
LIST_REMOVE(episode, blink);
_epg_object_set_updated((epg_object_t*)brand);
_epg_object_putref(brand);
_epg_object_set_updated(brand);
}
htsmsg_t *epg_brand_serialize ( epg_brand_t *brand )
{
htsmsg_t *m;
if ( !brand || !brand->uri ) return NULL;
if ( !(m = _epg_object_serialize((epg_object_t*)brand)) ) return NULL;
if ( !(m = _epg_object_serialize(brand)) ) return NULL;
if (brand->title)
htsmsg_add_str(m, "title", brand->title);
if (brand->summary)
@ -403,17 +408,13 @@ epg_brand_t *epg_brand_deserialize ( htsmsg_t *m, int create, int *save )
htsmsg_t *epg_brand_list ( void )
{
int i;
epg_object_t *eo;
htsmsg_t *a, *e;
a = htsmsg_create_list();
for ( i = 0; i < EPG_HASH_WIDTH; i++ ) {
LIST_FOREACH(eo, &epg_objects[i], id_link) {
if (eo->type == EPG_BRAND) {
e = epg_brand_serialize((epg_brand_t*)eo);
htsmsg_add_msg(a, NULL, e);
}
}
RB_FOREACH(eo, &epg_brands, uri_link) {
assert(eo->type == EPG_BRAND);
e = epg_brand_serialize((epg_brand_t*)eo);
htsmsg_add_msg(a, NULL, e);
}
return a;
}
@ -422,7 +423,7 @@ htsmsg_t *epg_brand_list ( void )
* Season
* *************************************************************************/
static void _epg_season_destroy ( epg_object_t *eo )
static void _epg_season_destroy ( void *eo )
{
epg_season_t *es = (epg_season_t*)eo;
if (LIST_FIRST(&es->episodes)) {
@ -430,16 +431,13 @@ static void _epg_season_destroy ( epg_object_t *eo )
assert(0);
}
_epg_object_destroy(eo, &epg_seasons);
if (es->brand) {
_epg_brand_rem_season(es->brand, es);
es->brand->putref((epg_object_t*)es->brand);
}
if (es->brand) _epg_brand_rem_season(es->brand, es);
if (es->summary) free(es->summary);
if (es->image) free(es->image);
free(es);
}
static void _epg_season_updated ( epg_object_t *eo )
static void _epg_season_updated ( void *eo )
{
dvr_autorec_check_season((epg_season_t*)eo);
}
@ -472,36 +470,26 @@ epg_season_t *epg_season_find_by_id ( uint64_t id )
int epg_season_set_summary ( epg_season_t *season, const char *summary )
{
if (!season || !summary) return 0;
return _epg_object_set_str(season, &season->summary, summary);
}
int epg_season_set_image ( epg_season_t *season, const char *image )
{
if (!season || !image) return 0;
return _epg_object_set_str(season, &season->image, image);
}
int epg_season_set_episode_count ( epg_season_t *season, uint16_t count )
{
int save = 0;
if ( !season || !count ) return 0;
if ( season->episode_count != count ) {
season->episode_count = count;
_epg_object_set_updated((epg_object_t*)season);
save = 1;
}
return save;
if (!season || !count) return 0;
return _epg_object_set_u16(season, &season->episode_count, count);
}
int epg_season_set_number ( epg_season_t *season, uint16_t number )
{
int save = 0;
if ( !season || !number ) return 0;
if ( season->number != number ) {
season->number = number;
_epg_object_set_updated((epg_object_t*)season);
save = 1;
}
return save;
if (!season || !number) return 0;
return _epg_object_set_u16(season, &season->number, number);
}
int epg_season_set_brand ( epg_season_t *season, epg_brand_t *brand, int u )
@ -509,14 +497,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->brand != brand ) {
if ( season->brand ) {
_epg_brand_rem_season(season->brand, season);
season->brand->putref((epg_object_t*)season->brand);
}
if ( season->brand ) _epg_brand_rem_season(season->brand, season);
season->brand = brand;
_epg_brand_add_season(brand, season);
brand->getref((epg_object_t*)brand);
_epg_object_set_updated((epg_object_t*)season);
_epg_object_set_updated(season);
save = 1;
}
return save;
@ -526,14 +510,16 @@ static void _epg_season_add_episode
( epg_season_t *season, epg_episode_t *episode )
{
LIST_INSERT_SORTED(&season->episodes, episode, slink, _episode_order);
_epg_object_set_updated((epg_object_t*)season);
_epg_object_getref(season);
_epg_object_set_updated(season);
}
static void _epg_season_rem_episode
( epg_season_t *season, epg_episode_t *episode )
{
LIST_REMOVE(episode, slink);
_epg_object_set_updated((epg_object_t*)season);
_epg_object_putref(season);
_epg_object_set_updated(season);
}
htsmsg_t *epg_season_serialize ( epg_season_t *season )
@ -609,8 +595,10 @@ static epg_episode_num_t *epg_episode_num_deserialize
const char *str;
uint32_t u32;
if (!m) return NULL;
if (!num) num = calloc(1, sizeof(epg_episode_num_t));
else memset(num, 0, sizeof(epg_episode_num_t));
if (!num)
num = calloc(1, sizeof(epg_episode_num_t));
else
memset(num, 0, sizeof(epg_episode_num_t));
if (!htsmsg_get_u32(m, "e_num", &u32))
num->e_num = u32;
if (!htsmsg_get_u32(m, "e_cnt", &u32))
@ -625,26 +613,19 @@ static epg_episode_num_t *epg_episode_num_deserialize
num->p_cnt = u32;
if ((str = htsmsg_get_str(m, "text")))
num->text = strdup(str);
return num;
}
static void _epg_episode_destroy ( epg_object_t *eo )
static void _epg_episode_destroy ( void *eo )
{
epg_episode_t *ee = (epg_episode_t*)eo;
epg_episode_t *ee = eo;
if (LIST_FIRST(&ee->broadcasts)) {
tvhlog(LOG_CRIT, "epg", "attempt to destroy episode with broadcasts");
assert(0);
}
_epg_object_destroy(eo, &epg_episodes);
if (ee->brand) {
_epg_brand_rem_episode(ee->brand, ee);
ee->brand->putref((epg_object_t*)ee->brand);
}
if (ee->season) {
_epg_season_rem_episode(ee->season, ee);
ee->season->putref((epg_object_t*)ee->season);
}
if (ee->brand) _epg_brand_rem_episode(ee->brand, ee);
if (ee->season) _epg_season_rem_episode(ee->season, ee);
if (ee->title) free(ee->title);
if (ee->subtitle) free(ee->subtitle);
if (ee->summary) free(ee->summary);
@ -655,7 +636,7 @@ static void _epg_episode_destroy ( epg_object_t *eo )
free(ee);
}
static void _epg_episode_updated ( epg_object_t *eo )
static void _epg_episode_updated ( void *eo )
{
}
@ -687,55 +668,46 @@ epg_episode_t *epg_episode_find_by_id ( uint64_t id )
int epg_episode_set_title ( epg_episode_t *episode, const char *title )
{
if (!episode || !title) return 0;
return _epg_object_set_str(episode, &episode->title, title);
}
int epg_episode_set_subtitle ( epg_episode_t *episode, const char *subtitle )
{
if (!episode || !subtitle) return 0;
return _epg_object_set_str(episode, &episode->subtitle, subtitle);
}
int epg_episode_set_summary ( epg_episode_t *episode, const char *summary )
{
if (!episode || !summary) return 0;
return _epg_object_set_str(episode, &episode->summary, summary);
}
int epg_episode_set_description ( epg_episode_t *episode, const char *desc )
{
if (!episode || !desc) return 0;
return _epg_object_set_str(episode, &episode->description, desc);
}
int epg_episode_set_image ( epg_episode_t *episode, const char *image )
{
if (!episode || !image) return 0;
return _epg_object_set_str(episode, &episode->image, image);
}
int epg_episode_set_number ( epg_episode_t *episode, uint16_t number )
{
int save = 0;
if ( !episode || !number ) return 0;
if ( episode->epnum.e_num != number ) {
episode->epnum.e_num = number;
_epg_object_set_updated((epg_object_t*)episode);
save = 1;
}
return save;
if (!episode || !number) return 0;
return _epg_object_set_u16(episode, &episode->epnum.e_num, number);
}
int epg_episode_set_part ( epg_episode_t *episode, uint16_t part, uint16_t count )
{
int save = 0;
if ( !episode || !part ) return 0;
if ( episode->epnum.p_num != part ) {
episode->epnum.p_num = part;
_epg_object_set_updated((epg_object_t*)episode);
save = 1;
}
if ( count && episode->epnum.p_cnt != count ) {
episode->epnum.p_cnt = count;
_epg_object_set_updated((epg_object_t*)episode);
save = 1;
}
if (!episode || !part) return 0;
save |= _epg_object_set_u16(episode, &episode->epnum.p_num, part);
save |= _epg_object_set_u16(episode, &episode->epnum.p_cnt, count);
return save;
}
@ -743,20 +715,20 @@ int epg_episode_set_epnum ( epg_episode_t *episode, epg_episode_num_t *num )
{
int save = 0;
if (!episode || !num || (!num->e_num && !num->text)) return 0;
if ( episode->epnum.e_num != num->e_num ) save = 1;
else if ( episode->epnum.e_cnt != num->e_cnt ) save = 1;
else if ( episode->epnum.s_num != num->s_num ) save = 1;
else if ( episode->epnum.s_cnt != num->s_cnt ) save = 1;
else if ( episode->epnum.p_num != num->p_num ) save = 1;
else if ( episode->epnum.p_cnt != num->p_cnt ) save = 1;
else if ( !episode->epnum.text ||
(num->text && strcmp(num->text, episode->epnum.text)) ) save = 1;
if (save) {
if (episode->epnum.text) free(episode->epnum.text);
episode->epnum = *num;
if (episode->epnum.text) strdup(episode->epnum.text);
save = 1;
}
if (num->s_num)
save |= _epg_object_set_u16(episode, &episode->epnum.s_num, num->s_num);
if (num->s_cnt)
save |= _epg_object_set_u16(episode, &episode->epnum.s_cnt, num->s_cnt);
if (num->e_num)
save |= _epg_object_set_u16(episode, &episode->epnum.e_num, num->e_num);
if (num->e_cnt)
save |= _epg_object_set_u16(episode, &episode->epnum.e_cnt, num->e_cnt);
if (num->p_num)
save |= _epg_object_set_u16(episode, &episode->epnum.p_num, num->p_num);
if (num->p_cnt)
save |= _epg_object_set_u16(episode, &episode->epnum.p_cnt, num->p_cnt);
if (num->text)
save |= _epg_object_set_str(episode, &episode->epnum.text, num->text);
return save;
}
@ -765,14 +737,10 @@ int epg_episode_set_brand ( epg_episode_t *episode, epg_brand_t *brand )
int save = 0;
if ( !episode || !brand ) return 0;
if ( episode->brand != brand ) {
if ( episode->brand ) {
_epg_brand_rem_episode(episode->brand, episode);
episode->brand->putref((epg_object_t*)episode->brand);
}
if ( episode->brand ) _epg_brand_rem_episode(episode->brand, episode);
episode->brand = brand;
_epg_brand_add_episode(brand, episode);
brand->getref((epg_object_t*)brand);
_epg_object_set_updated((epg_object_t*)episode);
_epg_object_set_updated(episode);
save = 1;
}
return save;
@ -783,15 +751,11 @@ int epg_episode_set_season ( epg_episode_t *episode, epg_season_t *season )
int save = 0;
if ( !episode || !season ) return 0;
if ( episode->season != season ) {
if ( episode->season ) {
_epg_season_rem_episode(episode->season, episode);
episode->season->putref((epg_object_t*)episode->season);
}
if ( episode->season ) _epg_season_rem_episode(episode->season, episode);
episode->season = season;
_epg_season_add_episode(season, episode);
season->getref((epg_object_t*)season);
if ( season->brand ) save |= epg_episode_set_brand(episode, season->brand);
_epg_object_set_updated((epg_object_t*)episode);
_epg_object_set_updated(episode);
save = 1;
}
return save;
@ -850,17 +814,18 @@ static void _epg_episode_add_broadcast
( epg_episode_t *episode, epg_broadcast_t *broadcast )
{
LIST_INSERT_SORTED(&episode->broadcasts, broadcast, ep_link, _ebc_start_cmp);
_epg_object_set_updated((epg_object_t*)episode);
_epg_object_getref(episode);
_epg_object_set_updated(episode);
}
static void _epg_episode_rem_broadcast
( epg_episode_t *episode, epg_broadcast_t *broadcast )
{
LIST_REMOVE(broadcast, ep_link);
_epg_object_set_updated((epg_object_t*)episode);
_epg_object_putref(episode);
_epg_object_set_updated(episode);
}
size_t epg_episode_number_format
( epg_episode_t *episode, char *buf, size_t len,
const char *pre, const char *sfmt,
@ -868,7 +833,7 @@ size_t epg_episode_number_format
const char *cfmt )
{
size_t i = 0;
if (!episode) return 0;
if (!episode || !buf || !len) return 0;
epg_episode_num_t num;
epg_episode_get_epnum(episode, &num);
if ( num.e_num ) {
@ -884,7 +849,7 @@ size_t epg_episode_number_format
i+= snprintf(&buf[i], len-i, cfmt, num.e_cnt);
} else if ( num.text ) {
strncpy(buf, num.text, len);
i = MAX(strlen(num.text), len);
i = strlen(buf);
}
return i;
}
@ -913,7 +878,6 @@ int epg_episode_number_cmp ( epg_episode_num_t *a, epg_episode_num_t *b )
}
}
// 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.
@ -957,7 +921,6 @@ epg_episode_t *epg_episode_deserialize ( htsmsg_t *m, int create, int *save )
epg_episode_t *ee;
epg_season_t *es;
epg_brand_t *eb;
uint32_t u32, u32a;
const char *str;
epg_episode_num_t num;
htsmsg_t *sub;
@ -978,13 +941,6 @@ epg_episode_t *epg_episode_deserialize ( htsmsg_t *m, int create, int *save )
*save |= epg_episode_set_epnum(ee, &num);
if (num.text) free(num.text);
}
// Note: retained for compat
if ( !htsmsg_get_u32(m, "number", &u32) )
*save |= epg_episode_set_number(ee, u32);
if ( !htsmsg_get_u32(m, "part-number", &u32) &&
!htsmsg_get_u32(m, "part-count", &u32a) )
*save |= epg_episode_set_part(ee, u32, u32a);
if ( (str = htsmsg_get_str(m, "season")) )
if ( (es = epg_season_find_by_uri(str, 0, NULL)) )
*save |= epg_episode_set_season(ee, es);
@ -1001,14 +957,23 @@ epg_episode_t *epg_episode_deserialize ( htsmsg_t *m, int create, int *save )
* Channel
* *************************************************************************/
static void _epg_channel_rem_broadcast
( channel_t *ch, epg_broadcast_t *ebc, epg_broadcast_t *new )
{
if (new) dvr_event_replaced(ebc, new);
RB_REMOVE(&ch->ch_epg_schedule, ebc, sched_link);
_epg_object_putref(ebc);
}
static void _epg_channel_timer_callback ( void *p )
{
time_t next = 0;
epg_broadcast_t *ebc, *cur;
epg_broadcast_t *ebc, *cur, *nxt;
channel_t *ch = (channel_t*)p;
/* Clear now/next */
cur = ch->ch_epg_now;
nxt = ch->ch_epg_next;
ch->ch_epg_now = ch->ch_epg_next = NULL;
/* Check events */
@ -1016,10 +981,9 @@ static void _epg_channel_timer_callback ( void *p )
/* Expire */
if ( ebc->stop <= dispatch_clock ) {
RB_REMOVE(&ch->ch_epg_schedule, ebc, sched_link);
tvhlog(LOG_DEBUG, "epg", "expire event %"PRIu64" from %s",
ebc->id, ch->ch_name);
ebc->putref((epg_object_t*)ebc);
_epg_channel_rem_broadcast(ch, ebc, NULL);
continue; // skip to next
/* No now */
@ -1035,10 +999,13 @@ static void _epg_channel_timer_callback ( void *p )
}
break;
}
tvhlog(LOG_DEBUG, "epg", "now/next %"PRIu64"/%"PRIu64" set on %s",
ch->ch_epg_now ? ch->ch_epg_now->id : 0,
ch->ch_epg_next ? ch->ch_epg_next->id : 0,
ch->ch_name);
/* Change */
if (cur != ch->ch_epg_now || nxt != ch->ch_epg_next)
tvhlog(LOG_DEBUG, "epg", "now/next %"PRIu64"/%"PRIu64" set on %s",
ch->ch_epg_now ? ch->ch_epg_now->id : 0,
ch->ch_epg_next ? ch->ch_epg_next->id : 0,
ch->ch_name);
/* re-arm */
if ( next ) {
@ -1055,14 +1022,6 @@ static void _epg_channel_timer_callback ( void *p )
}
}
static void _epg_channel_rem_broadcast
( channel_t *ch, epg_broadcast_t *ebc, epg_broadcast_t *new )
{
if (new) dvr_event_replaced(ebc, new);
RB_REMOVE(&ch->ch_epg_schedule, ebc, sched_link);
ebc->putref((epg_object_t*)ebc);
}
static epg_broadcast_t *_epg_channel_add_broadcast
( channel_t *ch, epg_broadcast_t **bcast, int create, int *save )
{
@ -1072,7 +1031,6 @@ static epg_broadcast_t *_epg_channel_add_broadcast
/* Set channel */
(*bcast)->channel = ch;
/* Find (only) */
if ( !create ) {
return RB_FIND(&ch->ch_epg_schedule, *bcast, sched_link, _ebc_start_cmp);
@ -1080,23 +1038,26 @@ static epg_broadcast_t *_epg_channel_add_broadcast
/* Find/Create */
} else {
ret = RB_INSERT_SORTED(&ch->ch_epg_schedule, *bcast, sched_link, _ebc_start_cmp);
/* New */
if (!ret) {
*save = 1;
ret = *bcast;
*bcast = NULL;
_epg_object_create((epg_object_t*)ret);
_epg_object_create(ret);
_epg_object_getref(ret);
/* No change */
} else if ( ret->stop == (*bcast)->stop ) {
return ret;
/* Extend in time */
} else {
ret->stop = (*bcast)->stop;
}
}
// Note: scheduling changes are relatively rare and therefore
// the rest of this code will happen infrequently (hopefully)
/* Grab ref */
ret->getref((epg_object_t*)ret);
/* Changed */
*save |= 1;
/* Remove overlapping (before) */
@ -1138,21 +1099,18 @@ void epg_channel_unlink ( channel_t *ch )
* Broadcast
* *************************************************************************/
static void _epg_broadcast_destroy ( epg_object_t *eo )
static void _epg_broadcast_destroy ( void *eo )
{
epg_broadcast_t *ebc = (epg_broadcast_t*)eo;
epg_broadcast_t *ebc = eo;
_epg_object_destroy(eo, NULL);
if (ebc->episode) {
_epg_episode_rem_broadcast(ebc->episode, ebc);
ebc->episode->putref((epg_object_t*)ebc->episode);
}
if (ebc->episode) _epg_episode_rem_broadcast(ebc->episode, ebc);
free(ebc);
}
static void _epg_broadcast_updated ( epg_object_t *eo )
static void _epg_broadcast_updated ( void *eo )
{
dvr_event_updated((epg_broadcast_t*)eo);
dvr_autorec_check_event((epg_broadcast_t*)eo);
dvr_event_updated(eo);
dvr_autorec_check_event(eo);
}
static epg_broadcast_t **_epg_broadcast_skel ( void )
@ -1205,14 +1163,10 @@ int epg_broadcast_set_episode
int save = 0;
if ( !broadcast || !episode ) return 0;
if ( broadcast->episode != episode ) {
if ( broadcast->episode ) {
_epg_episode_rem_broadcast(broadcast->episode, broadcast);
broadcast->episode->putref((epg_object_t*)broadcast->episode);
}
_epg_episode_add_broadcast(episode, broadcast);
if ( broadcast->episode ) _epg_episode_rem_broadcast(broadcast->episode, broadcast);
broadcast->episode = episode;
episode->getref((epg_object_t*)episode);
_epg_object_set_updated((epg_object_t*)broadcast);
_epg_episode_add_broadcast(episode, broadcast);
_epg_object_set_updated(broadcast);
save = 1;
}
return save;
@ -1317,7 +1271,7 @@ epg_broadcast_t *epg_broadcast_deserialize
( htsmsg_t *m, int create, int *save )
{
channel_t *ch = NULL;
epg_broadcast_t *ret, **ebc = _epg_broadcast_skel();
epg_broadcast_t *ebc, **skel = _epg_broadcast_skel();
epg_episode_t *ee;
const char *str;
uint32_t chid, eid, start, stop, u32;
@ -1331,55 +1285,49 @@ epg_broadcast_t *epg_broadcast_deserialize
if ( !(ee = epg_episode_find_by_uri(str, 0, NULL)) ) return NULL;
/* Set properties */
_epg_object_deserialize(m, (epg_object_t*)*ebc);
(*ebc)->start = start;
(*ebc)->stop = stop;
_epg_object_deserialize(m, (epg_object_t*)*skel);
(*skel)->start = start;
(*skel)->stop = stop;
/* Get DVB id */
if ( !htsmsg_get_u32(m, "dvb_eid", &eid) ) {
(*ebc)->dvb_eid = eid;
(*skel)->dvb_eid = eid;
}
/* Get channel */
if ( !htsmsg_get_u32(m, "channel", &chid) ) {
ch = channel_find_by_identifier(chid);
}
if (!ch) return NULL;
/* Create */
ebc = _epg_channel_add_broadcast(ch, skel, create, save);
if (!ebc) return NULL;
/* Get metadata */
if (!htsmsg_get_u32(m, "is_widescreen", &u32))
(*ebc)->is_widescreen = 1;
*save |= epg_broadcast_set_is_widescreen(ebc, u32);
if (!htsmsg_get_u32(m, "is_hd", &u32))
(*ebc)->is_hd = 1;
*save |= epg_broadcast_set_is_hd(ebc, u32);
if (!htsmsg_get_u32(m, "lines", &u32))
(*ebc)->lines = u32;
*save |= epg_broadcast_set_lines(ebc, u32);
if (!htsmsg_get_u32(m, "aspect", &u32))
(*ebc)->aspect = u32;
*save |= epg_broadcast_set_aspect(ebc, u32);
if (!htsmsg_get_u32(m, "is_deafsigned", &u32))
(*ebc)->is_deafsigned = 1;
*save |= epg_broadcast_set_is_deafsigned(ebc, u32);
if (!htsmsg_get_u32(m, "is_subtitled", &u32))
(*ebc)->is_subtitled = 1;
*save |= epg_broadcast_set_is_subtitled(ebc, u32);
if (!htsmsg_get_u32(m, "is_audio_desc", &u32))
(*ebc)->is_audio_desc = 1;
*save |= epg_broadcast_set_is_audio_desc(ebc, u32);
if (!htsmsg_get_u32(m, "is_new", &u32))
(*ebc)->is_new = 1;
*save |= epg_broadcast_set_is_new(ebc, u32);
if (!htsmsg_get_u32(m, "is_repeat", &u32))
(*ebc)->is_repeat = 1;
/* Add to channel */
if ( ch ) {
ret = _epg_channel_add_broadcast(ch, ebc, create, save);
/* Create dangling (possibly in use by DVR?) */
} else {
ret = *ebc;
_epg_object_create((epg_object_t*)*ebc);
*ebc = NULL;
}
*save |= epg_broadcast_set_is_repeat(ebc, u32);
/* Set the episode */
*save |= epg_broadcast_set_episode(ret, ee);
*save |= epg_broadcast_set_episode(ebc, ee);
return ret;
return ebc;
}
/* **************************************************************************

View file

@ -83,10 +83,10 @@ struct epg_object
int refcount; ///< Reference counting
// Note: could use LIST_ENTRY field to determine this!
void (*getref) ( epg_object_t* ); ///< Get a reference
void (*putref) ( epg_object_t* ); ///< Release a reference
void (*destroy) ( epg_object_t* ); ///< Delete the object
void (*updated) ( epg_object_t* ); ///< Updated
void (*getref) ( void *o ); ///< Get a reference
void (*putref) ( void *o ); ///< Release a reference
void (*destroy) ( void *o ); ///< Delete the object
void (*updated) ( void *o ); ///< Updated
};
/* ************************************************************************