Some more work on getting import from pyepg working. I think I have a slightly better idea how things are likely to work. Current broadcast search is probably a bit noddy, but will do for now.
This commit is contained in:
parent
9f247955fc
commit
cfb0179e80
3 changed files with 562 additions and 197 deletions
544
src/epg.c
544
src/epg.c
|
@ -16,6 +16,8 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// TODO:
|
||||
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdio.h>
|
||||
|
@ -38,6 +40,93 @@ struct epg_season_tree epg_seasons;
|
|||
struct epg_episode_tree epg_episodes;
|
||||
struct epg_channel_tree epg_channels;
|
||||
|
||||
/* **************************************************************************
|
||||
* Comparators
|
||||
* *************************************************************************/
|
||||
|
||||
static int eb_uri_cmp ( const epg_brand_t *a, const epg_brand_t *b )
|
||||
{
|
||||
return strcmp(a->eb_uri, b->eb_uri);
|
||||
}
|
||||
|
||||
static int es_uri_cmp ( const epg_season_t *a, const epg_season_t *b )
|
||||
{
|
||||
return strcmp(a->es_uri, b->es_uri);
|
||||
}
|
||||
|
||||
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 )
|
||||
{
|
||||
printf("check a %ld against b %ld to %ld\n", a->eb_start, b->eb_start, b->eb_stop);
|
||||
// TODO: some le-way?
|
||||
if ( a->eb_start < b->eb_start ) return -1;
|
||||
if ( a->eb_start >= b->eb_stop ) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* **************************************************************************
|
||||
* Testing/Debug
|
||||
* *************************************************************************/
|
||||
|
||||
static void _epg_dump ( void )
|
||||
{
|
||||
epg_brand_t *eb;
|
||||
epg_season_t *es;
|
||||
epg_episode_t *ee;
|
||||
epg_channel_t *ec;
|
||||
epg_broadcast_t *ebc;
|
||||
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\n", es, es->es_uri);
|
||||
RB_FOREACH(ee, &es->es_episodes, ee_slink) {
|
||||
printf(" EPISODE: %p %s\n", ee, ee->ee_uri);
|
||||
}
|
||||
}
|
||||
RB_FOREACH(ee, &eb->eb_episodes, ee_blink) {
|
||||
if ( !ee->ee_season ) printf(" EPISODE: %p %s\n", ee, ee->ee_uri);
|
||||
}
|
||||
}
|
||||
RB_FOREACH(es, &epg_seasons, es_link) {
|
||||
if ( !es->es_brand ) {
|
||||
printf("SEASON: %p %s\n", es, es->es_uri);
|
||||
RB_FOREACH(ee, &es->es_episodes, ee_slink) {
|
||||
printf(" EPISODE: %p %s\n", ee, ee->ee_uri);
|
||||
}
|
||||
}
|
||||
}
|
||||
RB_FOREACH(ee, &epg_episodes, ee_link) {
|
||||
if ( !ee->ee_brand && !ee->ee_season ) {
|
||||
printf("EPISODE: %p %s\n", ee, ee->ee_uri);
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* **************************************************************************
|
||||
* Setup / Update
|
||||
* *************************************************************************/
|
||||
|
||||
void epg_init ( void )
|
||||
{
|
||||
}
|
||||
|
@ -48,80 +137,13 @@ void epg_save ( void )
|
|||
|
||||
void epg_updated ( void )
|
||||
{
|
||||
_epg_dump();
|
||||
}
|
||||
|
||||
int epg_brand_set_title ( epg_brand_t *brand, const char *title )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int epg_brand_set_summary ( epg_brand_t *brand, const char *summary )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int epg_brand_set_season_count ( epg_brand_t *brand, uint16_t count )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int epg_season_set_brand ( epg_season_t *season, epg_brand_t *brand )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int epg_season_set_summary ( epg_season_t *season, const char *summary )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int epg_season_set_episode_count ( epg_season_t *season, uint16_t count )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int epg_season_set_number ( epg_season_t *season, uint16_t number )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int epg_episode_set_title ( epg_episode_t *episode, const char *title )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int epg_episode_set_subtitle ( epg_episode_t *episode, const char *title )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int epg_episode_set_summary ( epg_episode_t *episode, const char *summary )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int epg_episode_set_description ( epg_episode_t *episode, const char *desc )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int epg_episode_set_brand ( epg_episode_t *episode, epg_brand_t *brand )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int epg_episode_set_season ( epg_episode_t *episode, epg_season_t *season )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int epg_episode_set_number ( epg_episode_t *episode, uint16_t number )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int epg_episode_set_part ( epg_episode_t *episode, uint16_t part, uint16_t count )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int eb_uri_cmp ( const epg_brand_t *a, const epg_brand_t *b )
|
||||
{
|
||||
return strcmp(a->eb_uri, b->eb_uri);
|
||||
}
|
||||
/* **************************************************************************
|
||||
* Brand
|
||||
* *************************************************************************/
|
||||
|
||||
epg_brand_t* epg_brand_find_by_uri ( const char *id, int create )
|
||||
{
|
||||
|
@ -131,31 +153,123 @@ epg_brand_t* epg_brand_find_by_uri ( const char *id, int create )
|
|||
lock_assert(&global_lock); // pointless!
|
||||
|
||||
if ( skel == NULL ) skel = calloc(1, sizeof(epg_brand_t));
|
||||
skel->eb_uri = (char*)id;
|
||||
|
||||
/* Find */
|
||||
skel->eb_uri = (char*)id;
|
||||
eb = RB_FIND(&epg_brands, skel, eb_link, eb_uri_cmp);
|
||||
if ( eb ) printf("found brand %s @ %p\n", id, eb);
|
||||
if ( !create ) {
|
||||
eb = RB_FIND(&epg_brands, skel, eb_link, eb_uri_cmp);
|
||||
|
||||
/* Create */
|
||||
if ( !eb && create ) {
|
||||
} else {
|
||||
eb = RB_INSERT_SORTED(&epg_brands, skel, eb_link, eb_uri_cmp);
|
||||
if ( eb == NULL ) {
|
||||
eb = skel;
|
||||
skel = NULL;
|
||||
eb->eb_uri = strdup(id);
|
||||
printf("create brand %s @ %p\n", id, eb);
|
||||
}
|
||||
}
|
||||
|
||||
return eb;
|
||||
}
|
||||
|
||||
static int es_uri_cmp ( const epg_season_t *a, const epg_season_t *b )
|
||||
int epg_brand_set_title ( epg_brand_t *brand, const char *title )
|
||||
{
|
||||
return strcmp(a->es_uri, b->es_uri);
|
||||
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);
|
||||
save = 1;
|
||||
}
|
||||
return save;
|
||||
}
|
||||
|
||||
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);
|
||||
save = 1;
|
||||
}
|
||||
return save;
|
||||
}
|
||||
|
||||
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;
|
||||
save = 1;
|
||||
}
|
||||
return save;
|
||||
}
|
||||
|
||||
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);
|
||||
if ( es == NULL ) {
|
||||
if ( u ) save |= epg_season_set_brand(season, brand, 0);
|
||||
save = 1;
|
||||
}
|
||||
// TODO?: else assert(es == season)
|
||||
return save;
|
||||
}
|
||||
|
||||
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);
|
||||
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);
|
||||
save = 1;
|
||||
}
|
||||
return save;
|
||||
}
|
||||
|
||||
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);
|
||||
if ( ee == NULL ) {
|
||||
if ( u ) save |= epg_episode_set_brand(episode, brand, 0);
|
||||
save = 1;
|
||||
}
|
||||
// TODO?: else assert(ee == episode)
|
||||
return save;
|
||||
}
|
||||
|
||||
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);
|
||||
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);
|
||||
save = 1;
|
||||
}
|
||||
return save;
|
||||
}
|
||||
|
||||
/* **************************************************************************
|
||||
* Season
|
||||
* *************************************************************************/
|
||||
|
||||
epg_season_t* epg_season_find_by_uri ( const char *id, int create )
|
||||
{
|
||||
epg_season_t *es;
|
||||
|
@ -164,31 +278,108 @@ epg_season_t* epg_season_find_by_uri ( const char *id, int create )
|
|||
lock_assert(&global_lock); // pointless!
|
||||
|
||||
if ( skel == NULL ) skel = calloc(1, sizeof(epg_season_t));
|
||||
skel->es_uri = (char*)id;
|
||||
|
||||
/* Find */
|
||||
skel->es_uri = (char*)id;
|
||||
es = RB_FIND(&epg_seasons, skel, es_link, es_uri_cmp);
|
||||
if ( es ) printf("found season %s @ %p\n", id, es);
|
||||
if ( !create ) {
|
||||
es = RB_FIND(&epg_seasons, skel, es_link, es_uri_cmp);
|
||||
|
||||
/* Create */
|
||||
if ( !es && create ) {
|
||||
} else {
|
||||
es = RB_INSERT_SORTED(&epg_seasons, skel, es_link, es_uri_cmp);
|
||||
if ( es == NULL ) {
|
||||
es = skel;
|
||||
skel = NULL;
|
||||
es->es_uri = strdup(id);
|
||||
printf("create season %s @ %p\n", id, es);
|
||||
}
|
||||
}
|
||||
|
||||
return es;
|
||||
}
|
||||
|
||||
static int ee_uri_cmp ( const epg_episode_t *a, const epg_episode_t *b )
|
||||
int epg_season_set_summary ( epg_season_t *season, const char *summary )
|
||||
{
|
||||
return strcmp(a->ee_uri, b->ee_uri);
|
||||
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);
|
||||
save = 1;
|
||||
}
|
||||
return save;
|
||||
}
|
||||
|
||||
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;
|
||||
save = 1;
|
||||
}
|
||||
return save;
|
||||
}
|
||||
|
||||
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;
|
||||
save = 1;
|
||||
}
|
||||
return save;
|
||||
}
|
||||
|
||||
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);
|
||||
save = 1;
|
||||
}
|
||||
return save;
|
||||
}
|
||||
|
||||
int epg_season_add_episode
|
||||
( epg_season_t *season, epg_episode_t *episode, int u )
|
||||
{
|
||||
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);
|
||||
if ( ee == NULL ) {
|
||||
if ( u ) save |= epg_episode_set_season(episode, season, 0);
|
||||
save = 1;
|
||||
}
|
||||
// TODO?: else assert(ee == episode)
|
||||
return save;
|
||||
}
|
||||
|
||||
int epg_season_rem_episode
|
||||
( epg_season_t *season, epg_episode_t *episode, int u )
|
||||
{
|
||||
int save = 0;
|
||||
epg_episode_t *ee;
|
||||
if ( !season || !episode ) return 0;
|
||||
ee = RB_FIND(&season->es_episodes, episode, ee_slink, ee_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);
|
||||
save = 1;
|
||||
}
|
||||
return save;
|
||||
}
|
||||
|
||||
/* **************************************************************************
|
||||
* Episode
|
||||
* *************************************************************************/
|
||||
|
||||
epg_episode_t* epg_episode_find_by_uri ( const char *id, int create )
|
||||
{
|
||||
epg_episode_t *ee;
|
||||
|
@ -197,62 +388,215 @@ epg_episode_t* epg_episode_find_by_uri ( const char *id, int create )
|
|||
lock_assert(&global_lock); // pointless!
|
||||
|
||||
if ( skel == NULL ) skel = calloc(1, sizeof(epg_episode_t));
|
||||
skel->ee_uri = (char*)id;
|
||||
|
||||
/* Find */
|
||||
skel->ee_uri = (char*)id;
|
||||
ee = RB_FIND(&epg_episodes, skel, ee_link, ee_uri_cmp);
|
||||
if ( ee ) printf("found episode %s @ %p\n", id, ee);
|
||||
if ( !create ) {
|
||||
ee = RB_FIND(&epg_episodes, skel, ee_link, ee_uri_cmp);
|
||||
|
||||
/* Create */
|
||||
if ( !ee && create ) {
|
||||
} else {
|
||||
ee = RB_INSERT_SORTED(&epg_episodes, skel, ee_link, ee_uri_cmp);
|
||||
if ( ee == NULL ) {
|
||||
ee = skel;
|
||||
skel = NULL;
|
||||
ee->ee_uri = strdup(id);
|
||||
printf("create epsiode %s @ %p\n", id, ee);
|
||||
}
|
||||
}
|
||||
|
||||
return ee;
|
||||
}
|
||||
|
||||
static int ec_uri_cmp ( const epg_channel_t *a, const epg_channel_t *b )
|
||||
int epg_episode_set_title ( epg_episode_t *episode, const char *title )
|
||||
{
|
||||
return strcmp(a->ec_uri, b->ec_uri);
|
||||
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);
|
||||
save = 1;
|
||||
}
|
||||
return save;
|
||||
}
|
||||
|
||||
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);
|
||||
save = 1;
|
||||
}
|
||||
return save;
|
||||
}
|
||||
|
||||
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);
|
||||
save = 1;
|
||||
}
|
||||
return save;
|
||||
}
|
||||
|
||||
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);
|
||||
save = 1;
|
||||
}
|
||||
return save;
|
||||
}
|
||||
|
||||
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;
|
||||
save = 1;
|
||||
}
|
||||
return save;
|
||||
}
|
||||
|
||||
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;
|
||||
save |= 1;
|
||||
}
|
||||
if ( episode->ee_part_count != count ) {
|
||||
episode->ee_part_count = count;
|
||||
save |= 1;
|
||||
}
|
||||
return save;
|
||||
}
|
||||
|
||||
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);
|
||||
save |= 1;
|
||||
}
|
||||
return save;
|
||||
}
|
||||
|
||||
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);
|
||||
// TODO: is this the right place?
|
||||
}
|
||||
save = 1;
|
||||
}
|
||||
return save;
|
||||
}
|
||||
|
||||
/* **************************************************************************
|
||||
* Broadcast
|
||||
* *************************************************************************/
|
||||
|
||||
// Note: will find broadcast playing at this time (not necessarily
|
||||
// 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 )
|
||||
{
|
||||
epg_broadcast_t *eb;
|
||||
static epg_broadcast_t *skel = NULL;
|
||||
|
||||
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_start = start;
|
||||
skel->eb_stop = stop;
|
||||
|
||||
/* Find */
|
||||
if ( !create ) {
|
||||
eb = RB_FIND(&channel->ec_schedule, skel, eb_slink, ebc_win_cmp);
|
||||
|
||||
/* Create */
|
||||
} else {
|
||||
eb = RB_INSERT_SORTED(&channel->ec_schedule, skel, eb_slink, ebc_win_cmp);
|
||||
if ( eb == NULL ) {
|
||||
eb = skel;
|
||||
skel = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return eb;
|
||||
}
|
||||
|
||||
int epg_broadcast_set_episode
|
||||
( epg_broadcast_t *broadcast, epg_episode_t *episode, int u )
|
||||
{
|
||||
int save = 0;
|
||||
if ( !broadcast || !episode ) return 0;
|
||||
if ( broadcast->eb_episode != episode ) {
|
||||
broadcast->eb_episode = episode;
|
||||
//if ( u ) epg_episode_add_broadcast(episode, broadcast, 0);
|
||||
save = 1;
|
||||
}
|
||||
return save;
|
||||
}
|
||||
|
||||
/* **************************************************************************
|
||||
* Channel
|
||||
* *************************************************************************/
|
||||
|
||||
epg_channel_t* epg_channel_find_by_uri ( const char *id, int create )
|
||||
{
|
||||
epg_channel_t *ec;
|
||||
static epg_channel_t *skel = NULL;
|
||||
// TODO: is it really that beneficial to save a few bytes on the stack?
|
||||
// TODO: does this really need to be the global lock?
|
||||
|
||||
lock_assert(&global_lock); // pointless!
|
||||
|
||||
if ( skel == NULL ) skel = calloc(1, sizeof(epg_channel_t));
|
||||
skel->ec_uri = (char*)id;
|
||||
|
||||
/* Find */
|
||||
skel->ec_uri = (char*)id;
|
||||
ec = RB_FIND(&epg_channels, skel, ec_link, ec_uri_cmp);
|
||||
if ( ec ) printf("found channel %s @ %p\n", id, ec);
|
||||
if ( !create ) {
|
||||
ec = RB_FIND(&epg_channels, skel, ec_link, ec_uri_cmp);
|
||||
|
||||
/* Create */
|
||||
if ( !ec && create ) {
|
||||
} else {
|
||||
ec = RB_INSERT_SORTED(&epg_channels, skel, ec_link, ec_uri_cmp);
|
||||
if ( ec == NULL ) {
|
||||
ec = skel;
|
||||
skel = NULL;
|
||||
ec->ec_uri = strdup(id);
|
||||
printf("create channel %s @ %p\n", id, ec);
|
||||
}
|
||||
}
|
||||
|
||||
return ec;
|
||||
}
|
||||
|
||||
epg_channel_t* epg_channel_find ( const char *id, const char *name, const char **sname, const int **sid )
|
||||
epg_channel_t* epg_channel_find
|
||||
( const char *id, const char *name, const char **sname, const int **sid )
|
||||
{
|
||||
epg_channel_t* channel;
|
||||
|
||||
|
|
172
src/epg.h
172
src/epg.h
|
@ -34,10 +34,16 @@ struct epg_season;
|
|||
struct epg_episode;
|
||||
struct epg_broadcast;
|
||||
struct epg_channel;
|
||||
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);
|
||||
|
||||
/*
|
||||
* Map types
|
||||
*/
|
||||
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);
|
||||
// TODO: not sure above wants to be an RB, prob just LIST
|
||||
|
||||
/*
|
||||
* Represents a specific show
|
||||
|
@ -45,19 +51,18 @@ RB_HEAD(epg_channel_tree, epg_channel);
|
|||
*/
|
||||
typedef struct epg_brand
|
||||
{
|
||||
RB_ENTRY(epg_brand) eb_link;
|
||||
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
|
||||
RB_ENTRY(epg_brand) eb_link; ///< Global list link
|
||||
|
||||
LIST_HEAD(, epg_season_t) eb_seasons; ///< Attached seasons
|
||||
LIST_HEAD(, epg_episode_t) eb_episodes; ///< Un(-seasoned) episodes??
|
||||
char *eb_uri; ///< Grabber URI
|
||||
char *eb_title; ///< Brand name
|
||||
char *eb_summary; ///< Brand summary
|
||||
uint16_t eb_season_count; ///< Total number of seasons
|
||||
|
||||
struct epg_season_tree eb_seasons; ///< Season list
|
||||
struct epg_episode_tree eb_episodes; ///< Episode list
|
||||
// TODO: should this only include unattached episodes?
|
||||
|
||||
int eb_refcount; ///< Reference counting
|
||||
|
||||
int eb_refcount; ///< Reference counting
|
||||
} epg_brand_t;
|
||||
|
||||
/*
|
||||
|
@ -65,17 +70,18 @@ typedef struct epg_brand
|
|||
*/
|
||||
typedef struct epg_season
|
||||
{
|
||||
RB_ENTRY(epg_season) es_link;
|
||||
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
|
||||
RB_ENTRY(epg_season) es_link; ///< Global list link
|
||||
RB_ENTRY(epg_season) es_blink; ///< Brand list link
|
||||
|
||||
epg_brand_t *es_brand; ///< Parent brand
|
||||
LIST_HEAD(, epg_episode_t) es_episodes; ///< Child episodes
|
||||
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
|
||||
|
||||
int es_refcount; ///< Reference counting
|
||||
epg_brand_t *es_brand; ///< Parent brand
|
||||
struct epg_episode_tree es_episodes; ///< Episode list
|
||||
|
||||
int es_refcount; ///< Reference counting
|
||||
|
||||
} epg_season_t;
|
||||
|
||||
|
@ -84,23 +90,26 @@ typedef struct epg_season
|
|||
*/
|
||||
typedef struct epg_episode
|
||||
{
|
||||
RB_ENTRY(epg_episode) ee_link;
|
||||
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 (TODO: need a list?)
|
||||
uint16_t ee_number; ///< The episode number
|
||||
uint16_t ee_part_number; ///< For multipart episodes
|
||||
uint16_t ee_part_count; ///< For multipart episodes
|
||||
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_brand_t *ee_brand; ///< (Grand-)Parent brand
|
||||
epg_season_t *ee_season; ///< Parent season
|
||||
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
|
||||
// TODO: genre needs to be a list (should it be a string?)
|
||||
uint16_t ee_number; ///< The episode number
|
||||
uint16_t ee_part_number; ///< For multipart episodes
|
||||
uint16_t ee_part_count; ///< For multipart episodes
|
||||
|
||||
int ee_refcount; ///< Reference counting
|
||||
epg_brand_t *ee_brand; ///< (Grand-)Parent brand
|
||||
epg_season_t *ee_season; ///< Parent season
|
||||
struct epg_broadcast_tree ee_broadcasts; ///< Broadcast list
|
||||
|
||||
int ee_refcount; ///< Reference counting
|
||||
} epg_episode_t;
|
||||
|
||||
/*
|
||||
|
@ -108,27 +117,33 @@ typedef struct epg_episode
|
|||
*/
|
||||
typedef struct epg_broadcast
|
||||
{
|
||||
int eb_id; ///< Internal ID
|
||||
int eb_dvb_id; ///< DVB identifier
|
||||
time_t eb_start; ///< Start time
|
||||
time_t eb_stop; ///< End time
|
||||
epg_episode_t *eb_episode; ///< Episode shown
|
||||
channel_t* eb_channel; ///< Channel being broadcast on
|
||||
RB_ENTRY(epg_broadcast) eb_slink; ///< Schedule link
|
||||
RB_ENTRY(epg_broadcast) eb_elink; ///< Episode link
|
||||
|
||||
int eb_id; ///< Internal ID
|
||||
int eb_dvb_id; ///< DVB identifier
|
||||
time_t eb_start; ///< Start time
|
||||
time_t eb_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 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)
|
||||
|
||||
/* 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 eb_deafsigned; ///< In screen signing
|
||||
uint8_t eb_subtitled; ///< Teletext subtitles
|
||||
uint8_t eb_audio_desc; ///< Audio description
|
||||
|
||||
/* Misc flags */
|
||||
uint8_t eb_new; ///< New series / file premiere
|
||||
uint8_t eb_repeat; ///< Repeat screening
|
||||
uint8_t eb_new; ///< New series / file premiere
|
||||
uint8_t eb_repeat; ///< Repeat screening
|
||||
|
||||
epg_episode_t *eb_episode; ///< Episode shown
|
||||
channel_t *eb_channel; ///< Channel being broadcast on
|
||||
|
||||
int eb_refcount; ///< Reference counting
|
||||
} epg_broadcast_t;
|
||||
|
||||
/*
|
||||
|
@ -136,13 +151,16 @@ typedef struct epg_broadcast
|
|||
*/
|
||||
typedef struct epg_channel
|
||||
{
|
||||
RB_ENTRY(epg_channel) ec_link; ///< Link to channel map
|
||||
char *ec_uri; ///< Internal ID (defined by grabbers)
|
||||
char **ec_sname; ///< DVB service name (for searching)
|
||||
int **ec_sid; ///< DVB service ids (for searching)
|
||||
channel_t *ec_channel; ///< Link to real channel
|
||||
// TODO: further links?
|
||||
// TODO: reference counter?
|
||||
RB_ENTRY(epg_channel) ec_link; ///< Global link
|
||||
|
||||
char *ec_uri; ///< Channel URI
|
||||
char **ec_sname; ///< DVB svc names (to map)
|
||||
int **ec_sid; ///< DVB svc ids (to map)
|
||||
|
||||
channel_t *ec_channel; ///< Link to real channel
|
||||
|
||||
struct epg_broadcast_tree ec_schedule; ///< Schedule (broadcasts)
|
||||
|
||||
} epg_channel_t;
|
||||
|
||||
/*
|
||||
|
@ -178,30 +196,36 @@ void epg_save(void);
|
|||
*/
|
||||
|
||||
/* Brand set() calls */
|
||||
int epg_brand_set_uri ( epg_brand_t *b, const char *uri )
|
||||
__attribute__((warn_unused_result));
|
||||
int epg_brand_set_title ( epg_brand_t *b, const char *title )
|
||||
__attribute__((warn_unused_result));
|
||||
int epg_brand_set_summary ( epg_brand_t *b, const char *summary )
|
||||
__attribute__((warn_unused_result));
|
||||
__attribute__((warn_unused_result));
|
||||
int epg_brand_set_season_count ( epg_brand_t *b, uint16_t season_count )
|
||||
__attribute__((warn_unused_result));
|
||||
__attribute__((warn_unused_result));
|
||||
int epg_brand_add_season ( epg_brand_t *b, epg_season_t *s, int u )
|
||||
__attribute__((warn_unused_result));
|
||||
int epg_brand_rem_season ( epg_brand_t *b, epg_season_t *s, int u )
|
||||
__attribute__((warn_unused_result));
|
||||
int epg_brand_add_episode ( epg_brand_t *b, epg_episode_t *s, int u )
|
||||
__attribute__((warn_unused_result));
|
||||
int epg_brand_rem_episode ( epg_brand_t *b, epg_episode_t *s, int u )
|
||||
__attribute__((warn_unused_result));
|
||||
|
||||
/* Season set() calls */
|
||||
int epg_season_set_uri ( epg_season_t *s, const char *uri )
|
||||
__attribute__((warn_unused_result));
|
||||
int epg_season_set_summary ( epg_season_t *s, const char *summary )
|
||||
__attribute__((warn_unused_result));
|
||||
int epg_season_set_number ( epg_season_t *s, uint16_t number )
|
||||
__attribute__((warn_unused_result));
|
||||
int epg_season_set_episode_count ( epg_season_t *s, uint16_t episode_count )
|
||||
__attribute__((warn_unused_result));
|
||||
int epg_season_set_brand ( epg_season_t *s, epg_brand_t *b )
|
||||
int epg_season_set_brand ( epg_season_t *s, epg_brand_t *b, int u )
|
||||
__attribute__((warn_unused_result));
|
||||
int epg_season_add_episode ( epg_season_t *s, epg_episode_t *e, int u )
|
||||
__attribute__((warn_unused_result));
|
||||
int epg_season_rem_episode ( epg_season_t *s, epg_episode_t *e, int u )
|
||||
__attribute__((warn_unused_result));
|
||||
|
||||
/* Episode set() calls */
|
||||
int epg_episode_set_uri ( epg_episode_t *e, const char *uri )
|
||||
__attribute__((warn_unused_result));
|
||||
int epg_episode_set_title ( epg_episode_t *e, const char *title )
|
||||
__attribute__((warn_unused_result));
|
||||
int epg_episode_set_subtitle ( epg_episode_t *e, const char *subtitle )
|
||||
|
@ -215,14 +239,14 @@ int epg_episode_set_number ( epg_episode_t *e, uint16_t number )
|
|||
int epg_episode_set_part ( epg_episode_t *e,
|
||||
uint16_t number, uint16_t count )
|
||||
__attribute__((warn_unused_result));
|
||||
int epg_episode_set_brand ( epg_episode_t *e, epg_brand_t *b )
|
||||
int epg_episode_set_brand ( epg_episode_t *e, epg_brand_t *b, int u )
|
||||
__attribute__((warn_unused_result));
|
||||
int epg_episode_set_season ( epg_episode_t *e, epg_season_t *s )
|
||||
int epg_episode_set_season ( epg_episode_t *e, epg_season_t *s, int u )
|
||||
__attribute__((warn_unused_result));
|
||||
// Note: you don't need to call set_brand() if you set_season() using a season
|
||||
// on which you've called set_brand()
|
||||
|
||||
/* Broadcast set() calls */
|
||||
int epg_broadcast_set_episode ( epg_broadcast_t *b, epg_episode_t *e, int u )
|
||||
__attribute__((warn_unused_result));
|
||||
|
||||
// TODO: need to think how this will work with the new hierarchy
|
||||
void epg_updated ( void );
|
||||
|
@ -240,9 +264,7 @@ epg_season_t *epg_season_find_by_uri ( const char *uri, int create );
|
|||
epg_episode_t *epg_episode_find_by_uri ( const char *uri, int create );
|
||||
epg_channel_t *epg_channel_find_by_uri ( const char *uri, int create );
|
||||
epg_channel_t *epg_channel_find ( const char *uri, const char *name, const char **sname, const int **sid );
|
||||
epg_broadcast_t *epg_broadcast_find ( epg_channel_t *ch, epg_episode_t *ep, time_t start, time_t stop, int create );
|
||||
|
||||
epg_broadcast_t *epg_event_find_by_time(channel_t *ch, time_t t);
|
||||
epg_broadcast_t *epg_broadcast_find_by_time ( epg_channel_t *ch, time_t start, time_t stop, int create );
|
||||
|
||||
epg_broadcast_t *epg_event_find_by_id(int eventid);
|
||||
|
||||
|
|
|
@ -2,9 +2,11 @@
|
|||
* PyEPG grabber
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include "htsmsg_xml.h"
|
||||
#include "tvheadend.h"
|
||||
#include "spawn.h"
|
||||
|
@ -15,10 +17,15 @@
|
|||
* Parsing
|
||||
* *************************************************************************/
|
||||
|
||||
static int _pyepg_parse_time ( const char *str, time_t *tm )
|
||||
static int _pyepg_parse_time ( const char *str, time_t *out )
|
||||
{
|
||||
// TODO: implement
|
||||
return 0;
|
||||
int ret = 0;
|
||||
struct tm tm;
|
||||
if ( strptime(str, "%F %T %z", &tm) != NULL ) {
|
||||
*out = mktime(&tm);
|
||||
ret = 1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int _pyepg_parse_channel ( htsmsg_t *data )
|
||||
|
@ -33,7 +40,6 @@ static int _pyepg_parse_channel ( htsmsg_t *data )
|
|||
if ((attr = htsmsg_get_map(data, "attrib")) == NULL) return 0;
|
||||
if ((id = htsmsg_get_str(attr, "id")) == NULL) return 0;
|
||||
if ((tags = htsmsg_get_map(data, "tags")) == NULL) return 0;
|
||||
printf("parse_channel(%s)\n", id);
|
||||
|
||||
/* Find channel */
|
||||
if ((channel = epg_channel_find(id, name, NULL, NULL)) == NULL) return 0;
|
||||
|
@ -55,7 +61,6 @@ static int _pyepg_parse_brand ( htsmsg_t *data )
|
|||
if ((attr = htsmsg_get_map(data, "attrib")) == NULL) return 0;
|
||||
if ((str = htsmsg_get_str(attr, "id")) == NULL) return 0;
|
||||
if ((tags = htsmsg_get_map(data, "tags")) == NULL) return 0;
|
||||
printf("parse_brand(%s)\n", str);
|
||||
|
||||
/* Find brand */
|
||||
if ((brand = epg_brand_find_by_uri(str, 1)) == NULL) return 0;
|
||||
|
@ -100,18 +105,15 @@ static int _pyepg_parse_season ( htsmsg_t *data )
|
|||
if ((attr = htsmsg_get_map(data, "attrib")) == NULL) return 0;
|
||||
if ((str = htsmsg_get_str(attr, "id")) == NULL) return 0;
|
||||
if ((tags = htsmsg_get_map(data, "tags")) == NULL) return 0;
|
||||
printf("parse_season(%s)\n", str);
|
||||
|
||||
/* Find series */
|
||||
if ((season = epg_season_find_by_uri(str, 1)) == NULL) return 0;
|
||||
// TODO: do we need to save if created?
|
||||
printf("have season\n");
|
||||
|
||||
/* Set brand */
|
||||
if ((str = htsmsg_get_str(attr, "brand"))) {
|
||||
printf("lookup brand(%s)\n", str);
|
||||
if ((brand = epg_brand_find_by_uri(str, 0))) {
|
||||
save |= epg_season_set_brand(season, brand);
|
||||
save |= epg_season_set_brand(season, brand, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -160,26 +162,22 @@ static int _pyepg_parse_episode ( htsmsg_t *data )
|
|||
if ((attr = htsmsg_get_map(data, "attrib")) == NULL) return 0;
|
||||
if ((str = htsmsg_get_str(attr, "id")) == NULL) return 0;
|
||||
if ((tags = htsmsg_get_map(data, "tags")) == NULL) return 0;
|
||||
printf("parse_episode(%s)\n", str);
|
||||
|
||||
/* Find episode */
|
||||
if ((episode = epg_episode_find_by_uri(str, 1)) == NULL) return 0;
|
||||
// TODO: do we need to save if created?
|
||||
printf("have episode\n");
|
||||
|
||||
/* Set brand */
|
||||
if ((str = htsmsg_get_str(attr, "brand"))) {
|
||||
printf("lookup brand(%s)\n", str);
|
||||
if ((brand = epg_brand_find_by_uri(str, 0))) {
|
||||
save |= epg_episode_set_brand(episode, brand);
|
||||
save |= epg_episode_set_brand(episode, brand, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Set season */
|
||||
if ((str = htsmsg_get_str(attr, "series"))) {
|
||||
printf("lookup season(%s)\n", str);
|
||||
if ((season = epg_season_find_by_uri(str, 0))) {
|
||||
save |= epg_episode_set_season(episode, season);
|
||||
save |= epg_episode_set_season(episode, season, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -230,7 +228,6 @@ static int _pyepg_parse_broadcast ( htsmsg_t *data, epg_channel_t *channel )
|
|||
if ((id = htsmsg_get_str(attr, "episode")) == NULL) return 0;
|
||||
if ((start = htsmsg_get_str(attr, "start")) == NULL ) return 0;
|
||||
if ((stop = htsmsg_get_str(attr, "stop")) == NULL ) return 0;
|
||||
printf("parse_broadcast(ep=%s, start=%s, stop=%s)\n", id, start, stop);
|
||||
|
||||
/* Find episode */
|
||||
if ((episode = epg_episode_find_by_uri(id, 1)) == NULL) return 0;
|
||||
|
@ -240,9 +237,14 @@ static int _pyepg_parse_broadcast ( htsmsg_t *data, epg_channel_t *channel )
|
|||
if (!_pyepg_parse_time(stop, &tm_stop)) return 0;
|
||||
|
||||
/* Find broadcast */
|
||||
// TODO: need to think about this
|
||||
if ((broadcast = epg_broadcast_find(channel, episode, tm_start, tm_stop, 1)) == NULL) return 0;
|
||||
save = 1;
|
||||
printf("%s find broadcast %ld to %ld\n",
|
||||
channel->ec_uri, tm_start, tm_stop);
|
||||
broadcast = epg_broadcast_find_by_time(channel, tm_start, tm_stop, 1);
|
||||
printf("%s broadcast %p\n", channel->ec_uri, broadcast);
|
||||
if ( broadcast == NULL ) return 0;
|
||||
|
||||
/* Set episode */
|
||||
save |= epg_broadcast_set_episode(broadcast, episode, 1);
|
||||
|
||||
/* TODO: extra metadata */
|
||||
|
||||
|
@ -261,7 +263,6 @@ static int _pyepg_parse_schedule ( htsmsg_t *data )
|
|||
|
||||
if ((attr = htsmsg_get_map(data, "attrib")) == NULL) return 0;
|
||||
if ((str = htsmsg_get_str(attr, "channel")) == NULL) return 0;
|
||||
printf("parse_schedule(ch=%s)\n", str);
|
||||
if ((channel = epg_channel_find_by_uri(str, 0)) == NULL) return 0;
|
||||
if ((tags = htsmsg_get_map(data, "tags")) == NULL) return 0;
|
||||
|
||||
|
@ -279,7 +280,6 @@ static int _pyepg_parse_epg ( htsmsg_t *data )
|
|||
int save = 0;
|
||||
htsmsg_t *tags;
|
||||
htsmsg_field_t *f;
|
||||
printf("parse_epg()\n");
|
||||
|
||||
if ((tags = htsmsg_get_map(data, "tags")) == NULL) return 0;
|
||||
|
||||
|
@ -304,7 +304,6 @@ static int _pyepg_parse ( htsmsg_t *data )
|
|||
{
|
||||
htsmsg_t *tags, *epg;
|
||||
epggrab_module_t *mod;
|
||||
printf("parse()\n");
|
||||
|
||||
if ((tags = htsmsg_get_map(data, "tags")) == NULL) return 0;
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue