Some import now working, though only in as much as I am creating the various objects. They are not linked and no processing is done on them.

This commit is contained in:
Adam Sutton 2012-05-17 14:19:07 +01:00
parent d1dcaf4e69
commit 9f247955fc
4 changed files with 307 additions and 51 deletions

230
src/epg.c
View file

@ -33,3 +33,233 @@
#include "htsp.h"
#include "htsmsg_binary.h"
struct epg_brand_tree epg_brands;
struct epg_season_tree epg_seasons;
struct epg_episode_tree epg_episodes;
struct epg_channel_tree epg_channels;
void epg_init ( void )
{
}
void epg_save ( void )
{
}
void epg_updated ( void )
{
}
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);
}
epg_brand_t* epg_brand_find_by_uri ( const char *id, int create )
{
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));
/* 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);
/* Create */
if ( !eb && create ) {
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 )
{
return strcmp(a->es_uri, b->es_uri);
}
epg_season_t* epg_season_find_by_uri ( const char *id, int create )
{
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));
/* 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);
/* Create */
if ( !es && create ) {
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 )
{
return strcmp(a->ee_uri, b->ee_uri);
}
epg_episode_t* epg_episode_find_by_uri ( const char *id, int create )
{
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));
/* 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);
/* Create */
if ( !ee && create ) {
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 )
{
return strcmp(a->ec_uri, b->ec_uri);
}
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));
/* 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);
/* Create */
if ( !ec && create ) {
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* channel;
/* Find or create */
if ((channel = epg_channel_find_by_uri(id, 1)) == NULL) return NULL;
/* Update fields? */
return channel;
}

View file

@ -34,6 +34,10 @@ 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);
/*
* Represents a specific show
@ -41,6 +45,7 @@ struct 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
@ -60,6 +65,7 @@ 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
@ -78,6 +84,7 @@ 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
@ -129,6 +136,13 @@ 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?
} epg_channel_t;
/*
@ -182,7 +196,7 @@ 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, const epg_brand_t *b )
int epg_season_set_brand ( epg_season_t *s, epg_brand_t *b )
__attribute__((warn_unused_result));
/* Episode set() calls */
@ -221,11 +235,11 @@ void epg_broadcast_updated ( epg_broadcast_t *b );
* Simple lookup
*/
epg_brand_t *epg_brand_find_by_id ( const char *id, int create );
epg_season_t *epg_season_find_by_id ( const char *id, int create );
epg_episode_t *epg_episode_find_by_id ( const char *id, int create );
epg_channel_t *epg_channel_find_by_id ( const char *id, int create );
epg_channel_t *epg_channel_find ( const char *id, const char *name, const char **sname, const int **sid );
epg_brand_t *epg_brand_find_by_uri ( const char *uri, int create );
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);

View file

@ -4,6 +4,7 @@
#include "htsmsg.h"
#include "settings.h"
#include "tvheadend.h"
#include "epg.h"
#include "epggrab.h"
#include "epggrab/pyepg.h"
@ -52,13 +53,39 @@ void epggrab_init ( void )
pthread_create(&tid, &tattr, _epggrab_thread, NULL);
}
/*
* Grab from module
*/
static void _epggrab_module_run ( epggrab_module_t *mod, const char *opts )
{
int save = 0;
time_t tm1, tm2;
htsmsg_t *data;
/* Check */
if ( !mod ) return;
/* Grab */
time(&tm1);
data = mod->grab(opts);
time(&tm2);
if ( !data ) {
tvhlog(LOG_WARNING, mod->name(), "grab returned no data");
} else {
tvhlog(LOG_DEBUG, mod->name(), "grab took %d seconds", tm2 - tm1);
pthread_mutex_lock(&global_lock);
save = mod->parse(data);
if (save) epg_updated();
pthread_mutex_unlock(&global_lock);
htsmsg_destroy(data);
}
}
/*
* Simple run
*/
time_t _epggrab_thread_simple ( void )
{
htsmsg_t *data;
/* Copy config */
time_t ret = time(NULL) + epggrab_interval;
epggrab_module_t* mod = epggrab_module;
@ -67,15 +94,7 @@ time_t _epggrab_thread_simple ( void )
pthread_mutex_unlock(&epggrab_mutex);
/* Run the module */
if ( mod ) {
data = mod->grab(NULL);
if ( data ) {
pthread_mutex_lock(&global_lock);
mod->parse(data);
pthread_mutex_unlock(&global_lock);
htsmsg_destroy(data);
}
}
_epggrab_module_run(mod, NULL);
/* Re-lock */
pthread_mutex_lock(&epggrab_mutex);
@ -91,21 +110,12 @@ time_t _epggrab_thread_simple ( void )
*/
time_t _epggrab_thread_advanced ( void )
{
htsmsg_t *data;
epggrab_sched_t *s;
/* Determine which to run */
LIST_FOREACH(s, &epggrab_schedule, es_link) {
if ( cron_is_time(&s->cron) ) {
if ( s->mod ) {
data = s->mod->grab(s->opts);
if ( data ) {
pthread_mutex_lock(&global_lock);
s->mod->parse(data);
pthread_mutex_unlock(&global_lock);
htsmsg_destroy(data);
}
}
_epggrab_module_run(s->mod, s->opts);
}
}

View file

@ -33,6 +33,7 @@ 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;
@ -54,9 +55,10 @@ 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_id(str, 1)) == NULL) return 0;
if ((brand = epg_brand_find_by_uri(str, 1)) == NULL) return 0;
// TODO: do we need to save if created?
/* Set title */
@ -98,14 +100,17 @@ 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_id(str, 1)) == NULL) return 0;
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_xml_get_cdata_str(tags, "brand"))) {
if ((brand = epg_brand_find_by_id(str, 0))) {
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);
}
}
@ -155,21 +160,25 @@ 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_id(str, 1)) == NULL) return 0;
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_xml_get_cdata_str(tags, "brand"))) {
if ((brand = epg_brand_find_by_id(str, 0))) {
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);
}
}
/* Set season */
if ((str = htsmsg_xml_get_cdata_str(tags, "season"))) {
if ((season = epg_season_find_by_id(str, 0))) {
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);
}
}
@ -221,9 +230,10 @@ 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_id(id, 1)) == NULL) return 0;
if ((episode = epg_episode_find_by_uri(id, 1)) == NULL) return 0;
/* Parse times */
if (!_pyepg_parse_time(start, &tm_start)) return 0;
@ -251,11 +261,12 @@ 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;
if ((channel = epg_channel_find_by_id(str, 0)) == 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;
HTSMSG_FOREACH(f, tags) {
if (strcmp(f->hmf_name, "broadcast")) {
if (strcmp(f->hmf_name, "broadcast") == 0) {
save |= _pyepg_parse_broadcast(htsmsg_get_map_by_field(f), channel);
}
}
@ -268,6 +279,7 @@ 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;
@ -292,6 +304,7 @@ 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;
@ -326,8 +339,6 @@ static htsmsg_t* _pyepg_grab ( const char *iopts )
int i, outlen;
char *outbuf;
char errbuf[100];
time_t t1, t2;
htsmsg_t *body;
const char *argv[32]; // 32 args max!
char *toksave, *tok;
char *opts = NULL;
@ -349,24 +360,15 @@ static htsmsg_t* _pyepg_grab ( const char *iopts )
tvhlog(LOG_DEBUG, "pyepg", "grab %s %s", argv[0], iopts ? iopts : "");
/* Grab */
time(&t1);
outlen = spawn_and_store_stdout(argv[0], (char *const*)argv, &outbuf);
free(opts);
if ( outlen < 1 ) {
tvhlog(LOG_ERR, "pyepg", "no output detected");
return NULL;
}
time(&t2);
tvhlog(LOG_DEBUG, "pyepg", "grab took %d seconds", t2 - t1);
/* Extract */
body = htsmsg_xml_deserialize(outbuf, errbuf, sizeof(errbuf));
if ( !body ) {
tvhlog(LOG_ERR, "pyepg", "unable to parse output [e=%s]", errbuf);
return NULL;
}
return body;
return htsmsg_xml_deserialize(outbuf, errbuf, sizeof(errbuf));
}
epggrab_module_t* pyepg_init ( void )