if(ch)
addtag(q, build_tag_string("TVCHANNEL", ch->ch_name, 0, NULL));
-#if TODO_EP_NUMBER_ONSCREEN
- if(ee && ee->onscreen)
- addtag(q, build_tag_string("SYNOPSIS",
- ee->onscreen, 0, NULL));
-#endif
-
if(de && de->de_desc)
addtag(q, build_tag_string("SUMMARY", de->de_desc, 0, NULL));
else if (ee && ee->description)
addtag(q, build_tag_string("SUMMARY", ee->summary, 0, NULL));
if (ee) {
- if(ee->number)
- addtag(q, build_tag_int("PART_NUMBER", ee->number,
+ epg_episode_num_t num;
+ epg_episode_get_epnum(ee, &num);
+ if(num.e_num)
+ addtag(q, build_tag_int("PART_NUMBER", num.e_num,
0, NULL));
- if(ee->season && ee->season->number)
- addtag(q, build_tag_int("PART_NUMBER", ee->season->number,
+ if(num.s_num)
+ addtag(q, build_tag_int("PART_NUMBER", num.s_num,
60, "SEASON"));
- if(ee->part_number)
- addtag(q, build_tag_int("PART_NUMBER", ee->part_number,
+ if(num.p_num)
+ addtag(q, build_tag_int("PART_NUMBER", num.p_num,
40, "PART"));
+ if (num.text)
+ addtag(q, build_tag_string("SYNOPSIS",
+ num.text, 0, NULL));
}
return q;
return a->number - b->number;
}
+// Note: this will do nothing with text episode numbering
static int _episode_order ( const void *_a, const void *_b )
{
- int r;
+ int r, as, bs;
const epg_episode_t *a = (const epg_episode_t*)_a;
const epg_episode_t *b = (const epg_episode_t*)_b;
- r = _season_order(a->season, b->season);
+ if (!a) return -1;
+ if (!b) return 1;
+ if (a->season) as = a->season->number;
+ else as = a->epnum.s_num;
+ if (b->season) bs = b->season->number;
+ else bs = b->epnum.s_num;
+ r = as - bs;
if (r) return r;
- if (!a || !a->number) return 1;
- if (!b || !b->number) return -1;
- return a->number - b->number;
+ r = a->epnum.e_num - b->epnum.e_num;
+ if (r) return r;
+ return a->epnum.p_num - b->epnum.p_num;
}
/* **************************************************************************
* Episode
* *************************************************************************/
+static htsmsg_t *epg_episode_num_serialize ( epg_episode_num_t *num )
+{
+ htsmsg_t *m;
+ if (!num) return NULL;
+ m = htsmsg_create_map();
+ if (num->e_num)
+ htsmsg_add_u32(m, "e_num", num->e_num);
+ if (num->e_cnt)
+ htsmsg_add_u32(m, "e_cnt", num->e_cnt);
+ if (num->s_num)
+ htsmsg_add_u32(m, "s_num", num->e_num);
+ if (num->s_cnt)
+ htsmsg_add_u32(m, "s_cnt", num->e_cnt);
+ if (num->p_num)
+ htsmsg_add_u32(m, "p_num", num->e_num);
+ if (num->p_cnt)
+ htsmsg_add_u32(m, "p_cnt", num->e_cnt);
+ if (num->text)
+ htsmsg_add_str(m, "text", num->text);
+ return m;
+}
+
+static epg_episode_num_t *epg_episode_num_deserialize
+ ( htsmsg_t *m, epg_episode_num_t *num )
+{
+ const char *str;
+ uint32_t u32;
+ if (!m) return NULL;
+ if (!num) num = calloc(1, 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))
+ num->e_cnt = u32;
+ if (!htsmsg_get_u32(m, "s_num", &u32))
+ num->s_num = u32;
+ if (!htsmsg_get_u32(m, "s_cnt", &u32))
+ num->s_cnt = u32;
+ if (!htsmsg_get_u32(m, "p_num", &u32))
+ num->p_num = u32;
+ if (!htsmsg_get_u32(m, "p_cnt", &u32))
+ 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 )
{
epg_episode_t *ee = (epg_episode_t*)eo;
if (ee->description) free(ee->description);
if (ee->genre) free(ee->genre);
if (ee->image) free(ee->image);
+ if (ee->epnum.text) free(ee->epnum.text);
free(ee);
}
{
int save = 0;
if ( !episode || !number ) return 0;
- if ( episode->number != number ) {
- episode->number = number;
+ if ( episode->epnum.e_num != number ) {
+ episode->epnum.e_num = number;
_epg_object_set_updated((epg_object_t*)episode);
save = 1;
}
{
int save = 0;
if ( !episode || !part ) return 0;
- if ( episode->part_number != part ) {
- episode->part_number = part;
+ if ( episode->epnum.p_num != part ) {
+ episode->epnum.p_num = part;
_epg_object_set_updated((epg_object_t*)episode);
save = 1;
}
- if ( count && episode->part_count != count ) {
- episode->part_count = count;
+ if ( count && episode->epnum.p_cnt != count ) {
+ episode->epnum.p_cnt = count;
_epg_object_set_updated((epg_object_t*)episode);
save = 1;
}
return save;
}
+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;
+ }
+ return save;
+}
+
int epg_episode_set_brand ( epg_episode_t *episode, epg_brand_t *brand )
{
int save = 0;
size_t i = 0;
if (!episode) return 0;
epg_episode_num_t num;
- epg_episode_number_full(episode, &num);
+ epg_episode_get_epnum(episode, &num);
if ( num.e_num ) {
if (pre) i += snprintf(&buf[i], len-i, "%s", pre);
if ( sfmt && num.s_num ) {
i += snprintf(&buf[i], len-i, efmt, num.e_num);
if ( cfmt && num.e_cnt )
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);
}
return i;
}
-void epg_episode_number_full ( epg_episode_t *ee, epg_episode_num_t *num )
+void epg_episode_get_epnum ( epg_episode_t *ee, epg_episode_num_t *num )
{
if (!ee || !num) return;
- memset(num, 0, sizeof(epg_episode_num_t));
- num->e_num = ee->number;
- num->p_num = ee->part_number;
- num->p_cnt = ee->part_count;
+ *num = ee->epnum;
if (ee->season) {
num->e_cnt = ee->season->episode_count;
num->s_num = ee->season->number;
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);
- }
+ htsmsg_add_msg(m, "epnum", epg_episode_num_serialize(&episode->epnum));
if (episode->brand)
htsmsg_add_str(m, "brand", episode->brand->uri);
if (episode->season)
epg_brand_t *eb;
uint32_t u32, u32a;
const char *str;
+ epg_episode_num_t num;
+ htsmsg_t *sub;
if ( !_epg_object_deserialize(m, *skel) ) return NULL;
if ( !(ee = epg_episode_find_by_uri((*skel)->uri, create, save)) ) return NULL;
*save |= epg_episode_set_summary(ee, str);
if ( (str = htsmsg_get_str(m, "description")) )
*save |= epg_episode_set_description(ee, str);
+ if ( (sub = htsmsg_get_map(m, "epnum")) ) {
+ epg_episode_num_deserialize(sub, &num);
+ *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) &&
*/
typedef struct epg_episode_num
{
- uint16_t s_num; ///< Series number
- uint16_t s_cnt; ///< Series count
- uint16_t e_num; ///< Episode number
- uint16_t e_cnt; ///< Episode count
- uint16_t p_num; ///< Part number
- uint16_t p_cnt; ///< Part count
+ uint16_t s_num; ///< Series number
+ uint16_t s_cnt; ///< Series count
+ uint16_t e_num; ///< Episode number
+ uint16_t e_cnt; ///< Episode count
+ uint16_t p_num; ///< Part number
+ uint16_t p_cnt; ///< Part count
+ char *text; ///< Arbitary text description of episode num
} epg_episode_num_t;
/* Object */
char *description; ///< An extended description
uint8_t *genre; ///< Episode genre(s)
int genre_cnt; ///< Genre count
- uint16_t number; ///< The episode number
- uint16_t part_number; ///< For multipart episodes
- uint16_t part_count; ///< For multipart episodes
+ epg_episode_num_t epnum; ///< Episode numbering
+ // Note: do not use epnum directly! use the accessor routine
char *image; ///< Episode image
// TODO: certification and rating
__attribute__((warn_unused_result));
int epg_episode_set_number ( epg_episode_t *e, uint16_t number )
__attribute__((warn_unused_result));
-int epg_episode_set_onscreen ( epg_episode_t *e, const char *onscreen )
- __attribute__((warn_unused_result));
int epg_episode_set_part ( epg_episode_t *e,
uint16_t number, uint16_t count )
__attribute__((warn_unused_result));
+int epg_episode_set_epnum ( epg_episode_t *e, epg_episode_num_t *num )
+ __attribute__((warn_unused_result));
int epg_episode_set_brand ( epg_episode_t *e, epg_brand_t *b )
__attribute__((warn_unused_result));
int epg_episode_set_season ( epg_episode_t *e, epg_season_t *s )
int epg_episode_set_image ( epg_episode_t *e, const char *i )
__attribute__((warn_unused_result));
+// Note: this does NOT strdup the text field
+void epg_episode_get_epnum
+ ( epg_episode_t *e, epg_episode_num_t *epnum );
/* EpNum format helper */
// output string will be:
// if (episode_num)
const char *pre, const char *sfmt,
const char *sep, const char *efmt,
const char *cfmt );
-void epg_episode_number_full
- ( epg_episode_t *e, epg_episode_num_t *epnum );
int epg_episode_number_cmp
( epg_episode_num_t *a, epg_episode_num_t *b );