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:
parent
d1dcaf4e69
commit
9f247955fc
4 changed files with 307 additions and 51 deletions
230
src/epg.c
230
src/epg.c
|
@ -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;
|
||||
}
|
||||
|
|
26
src/epg.h
26
src/epg.h
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 )
|
||||
|
|
Loading…
Add table
Reference in a new issue