Start work on epg load/save and also added back in initial xmltv parser.

This commit is contained in:
Adam Sutton 2012-05-22 10:15:05 +01:00
parent a78994729e
commit 988eb8133a
7 changed files with 335 additions and 897 deletions

View file

@ -73,7 +73,9 @@ SRCS = src/main.c \
src/iptv_input.c \
src/avc.c \
SRCS += src/epggrab/pyepg.c
SRCS += src/epggrab/pyepg.c\
src/epggrab/xmltv.c
SRCS += src/plumbing/tsfix.c \

170
src/epg.c
View file

@ -148,12 +148,85 @@ static void _epg_dump ( void )
* Setup / Update
* *************************************************************************/
void epg_init ( void )
static int _epg_write ( int fd, htsmsg_t *m )
{
int ret = 1;
size_t msglen;
void *msgdata;
if (m) {
int r = htsmsg_binary_serialize(m, &msgdata, &msglen, 0x10000);
htsmsg_destroy(m);
if (!r) {
ssize_t w = write(fd, msgdata, msglen);
free(msgdata);
if(w == msglen) ret = 0;
}
}
if(ret) {
tvhlog(LOG_DEBUG, "epg", "failed to store epg to disk");
close(fd);
hts_settings_remove("epgdb");
}
return ret;
}
void epg_save ( void )
{
int fd;
epg_brand_t *eb;
epg_season_t *es;
epg_episode_t *ee;
epg_channel_t *ec;
epg_broadcast_t *ebc;
printf("EPG save\n");
// TODO: requires markers in the file or some other means of
// determining where the various object types are?
fd = hts_settings_open_file(1, "epgdb");
RB_FOREACH(ec, &epg_channels, ec_link) {
if (_epg_write(fd, epg_channel_serialize(ec))) return;
}
RB_FOREACH(eb, &epg_brands, eb_link) {
if (_epg_write(fd, epg_brand_serialize(eb))) return;
}
RB_FOREACH(es, &epg_seasons, es_link) {
if (_epg_write(fd, epg_season_serialize(es))) return;
}
RB_FOREACH(ee, &epg_episodes, ee_link) {
if (_epg_write(fd, epg_episode_serialize(ee))) return;
}
RB_FOREACH(ec, &epg_channels, ec_link) {
RB_FOREACH(ebc, &ec->ec_schedule, eb_slink) {
if (_epg_write(fd, epg_broadcast_serialize(ebc))) return;
}
}
}
void epg_init ( void )
{
struct stat st;
int fd = hts_settings_open_file(0, "epgdb");
size_t remain;
uint8_t *mem, *rp;
fstat(fd, &st);
rp = mem = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
//TODO:if ( mem == MAP_FAILED ) return;
remain = st.st_size;
while ( remain > 4 ) {
int msglen = (rp[0] << 24) | (rp[1] << 16) | (rp[2] << 8) | rp[3];
printf("msglen = %d\n", msglen);
remain -= 4;
rp += 4;
htsmsg_t *m = htsmsg_binary_deserialize(rp, msglen, NULL);
if(m) {
htsmsg_print(m);
htsmsg_destroy(m);
}
rp += msglen;
remain -= msglen;
}
munmap(mem, st.st_size);
close(fd);
}
void epg_updated ( void )
@ -306,6 +379,23 @@ int epg_brand_rem_episode ( epg_brand_t *brand, epg_episode_t *episode, int u )
return save;
}
htsmsg_t *epg_brand_serialize ( epg_brand_t *brand )
{
htsmsg_t *m;
if ( !brand ) return NULL;
m = htsmsg_create_map();
// TODO: ID
if (brand->eb_uri)
htsmsg_add_str(m, "uri", brand->eb_uri);
if (brand->eb_title)
htsmsg_add_str(m, "title", brand->eb_title);
if (brand->eb_summary)
htsmsg_add_str(m, "summary", brand->eb_summary);
if (brand->eb_season_count)
htsmsg_add_u32(m, "season-count", brand->eb_season_count);
return m;
}
/* **************************************************************************
* Season
* *************************************************************************/
@ -416,6 +506,25 @@ int epg_season_rem_episode
return save;
}
htsmsg_t *epg_season_serialize ( epg_season_t *season )
{
htsmsg_t *m;
if (!season) return NULL;
m = htsmsg_create_map();
if (season->es_uri)
htsmsg_add_str(m, "uri", season->es_uri);
if (season->es_summary)
htsmsg_add_str(m, "summary", season->es_summary);
if (season->es_number)
htsmsg_add_u32(m, "number", season->es_number);
if (season->es_episode_count)
htsmsg_add_u32(m, "episode-count", season->es_episode_count);
if (season->es_brand)
htsmsg_add_str(m, "brand-id", season->es_brand->eb_uri);
// TODO: change to ID
return m;
}
/* **************************************************************************
* Episode
* *************************************************************************/
@ -596,6 +705,35 @@ int epg_episode_get_number_onscreen
return i;
}
htsmsg_t *epg_episode_serialize ( epg_episode_t *episode )
{
htsmsg_t *m;
if (!episode) return NULL;
m = htsmsg_create_map();
if (episode->ee_uri)
htsmsg_add_str(m, "uri", episode->ee_uri);
if (episode->ee_title)
htsmsg_add_str(m, "title", episode->ee_title);
if (episode->ee_subtitle)
htsmsg_add_str(m, "subtitle", episode->ee_subtitle);
if (episode->ee_summary)
htsmsg_add_str(m, "summary", episode->ee_summary);
if (episode->ee_description)
htsmsg_add_str(m, "description", episode->ee_description);
if (episode->ee_number)
htsmsg_add_u32(m, "number", episode->ee_number);
if (episode->ee_part_count && episode->ee_part_count) {
htsmsg_add_u32(m, "part-number", episode->ee_part_number);
htsmsg_add_u32(m, "part-count", episode->ee_part_count);
}
// TODO: use ids
if (episode->ee_brand)
htsmsg_add_str(m, "brand-id", episode->ee_brand->eb_uri);
if (episode->ee_season)
htsmsg_add_str(m, "season-id", episode->ee_season->es_uri);
return m;
}
/* **************************************************************************
* Broadcast
* *************************************************************************/
@ -672,6 +810,23 @@ epg_broadcast_t *epg_broadcast_get_next ( epg_broadcast_t *broadcast )
return RB_NEXT(broadcast, eb_slink);
}
htsmsg_t *epg_broadcast_serialize ( epg_broadcast_t *broadcast )
{
htsmsg_t *m;
if (!broadcast) return NULL;
m = htsmsg_create_map();
htsmsg_add_u32(m, "id", broadcast->eb_id);
htsmsg_add_u32(m, "start", broadcast->eb_start);
htsmsg_add_u32(m, "stop", broadcast->eb_stop);
if (broadcast->eb_dvb_id)
htsmsg_add_u32(m, "dvb-id", broadcast->eb_dvb_id);
// TODO: add other metadata fields
// TODO: use ID
if (broadcast->eb_episode)
htsmsg_add_str(m, "episode-id", broadcast->eb_episode->ee_uri);
return m;
}
/* **************************************************************************
* Channel
* *************************************************************************/
@ -732,6 +887,19 @@ epg_broadcast_t *epg_channel_get_current_broadcast ( epg_channel_t *channel )
return RB_FIRST(&channel->ec_schedule);
}
htsmsg_t *epg_channel_serialize ( epg_channel_t *channel )
{
htsmsg_t *m;
if (!channel) return NULL;
m = htsmsg_create_map();
if (channel->ec_uri)
htsmsg_add_str(m, "uri", channel->ec_uri);
if (channel->ec_channel)
htsmsg_add_u32(m, "channel-id", channel->ec_channel->ch_id);
// TODO: other data
return m;
}
/* **************************************************************************
* Querying
* *************************************************************************/

View file

@ -80,6 +80,10 @@ int epg_brand_add_episode ( epg_brand_t *b, epg_episode_t *s, int u )
int epg_brand_rem_episode ( epg_brand_t *b, epg_episode_t *s, int u )
__attribute__((warn_unused_result));
/* Serialization */
htsmsg_t *epg_brand_serialize ( epg_brand_t *b );
epg_brand_t *epg_brand_deserialize ( htsmsg_t *m, int create );
/* ************************************************************************
* Season
* ***********************************************************************/
@ -119,6 +123,10 @@ int epg_season_add_episode ( epg_season_t *s, epg_episode_t *e, int u )
int epg_season_rem_episode ( epg_season_t *s, epg_episode_t *e, int u )
__attribute__((warn_unused_result));
/* Serialization */
htsmsg_t *epg_season_serialize ( epg_season_t *b );
epg_season_t *epg_season_deserialize ( htsmsg_t *m, int create );
/* ************************************************************************
* Episode
*
@ -178,6 +186,9 @@ int epg_episode_rem_broadcast ( epg_episode_t *e, epg_broadcast_t *b, int u )
/* Acessors */
int epg_episode_get_number_onscreen ( epg_episode_t *e, char *b, int c );
/* Serialization */
htsmsg_t *epg_episode_serialize ( epg_episode_t *b );
epg_episode_t *epg_episode_deserialize ( htsmsg_t *m, int create );
/* ************************************************************************
* Broadcast - specific airing (channel & time) of an episode
@ -226,6 +237,10 @@ int epg_broadcast_set_episode ( epg_broadcast_t *b, epg_episode_t *e, int u )
/* Accessors */
epg_broadcast_t *epg_broadcast_get_next ( epg_broadcast_t *b );
/* Serialization */
htsmsg_t *epg_broadcast_serialize ( epg_broadcast_t *b );
epg_broadcast_t *epg_broadcast_deserialize ( htsmsg_t *m, int create );
/* ************************************************************************
* Channel - provides mapping from EPG channels to real channels
* ***********************************************************************/
@ -257,6 +272,10 @@ int epg_channel_set_name ( epg_channel_t *c, const char *n )
/* Accessors */
epg_broadcast_t *epg_channel_get_current_broadcast ( epg_channel_t *c );
/* Serialization */
htsmsg_t *epg_channel_serialize ( epg_channel_t *b );
epg_channel_t *epg_channel_deserialize ( htsmsg_t *m, int create );
/* ************************************************************************
* Querying
* ***********************************************************************/

View file

@ -7,6 +7,7 @@
#include "epg.h"
#include "epggrab.h"
#include "epggrab/pyepg.h"
#include "epggrab/xmltv.h"
/* Thread protection */
int epggrab_confver;
@ -22,6 +23,7 @@ epggrab_sched_list_t epggrab_schedule;
/* Modules */
epggrab_module_t* epggrab_module_pyepg;
epggrab_module_t* epggrab_module_xmltv;
/* Internal prototypes */
static void* _epggrab_thread ( void* );
@ -44,6 +46,7 @@ void epggrab_init ( void )
/* Initialise modules */
epggrab_module_pyepg = pyepg_init();
epggrab_module_xmltv = xmltv_init();
/* Start thread */
pthread_t tid;
@ -163,6 +166,7 @@ void* _epggrab_thread ( void* p )
epggrab_module_t* epggrab_module_find_by_name ( const char *name )
{
if ( strcmp(name, "pyepg") == 0 ) return epggrab_module_pyepg;
if ( strcmp(name, "xmltv") == 0 ) return epggrab_module_xmltv;
return NULL;
}

View file

@ -4,4 +4,9 @@
#include "epggrab.h"
#ifndef EPGGRAB_PYEPG_H
#define EPGGRAB_PYEPG_H
epggrab_module_t* pyepg_init ( void );
#endif

File diff suppressed because it is too large Load diff

View file

@ -16,46 +16,11 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef EPG_XMLTV_H
#define EPG_XMLTV_H
#ifndef EPGGRAB_XMLTV_H
#define EPGGRAB_XMLTV_H
#include "channels.h"
#include "epggrab.h"
RB_HEAD(xmltv_channel_tree, xmltv_channel);
LIST_HEAD(xmltv_channel_list, xmltv_channel);
epggrab_module_t *xmltv_init ( void );
/**
* A channel in the XML-TV world
*/
typedef struct xmltv_channel {
RB_ENTRY(xmltv_channel) xc_link;
char *xc_identifier;
LIST_ENTRY(xmltv_channel) xc_displayname_link;
char *xc_displayname;
char *xc_icon;
struct channel_list xc_channels; /* Target channel(s) */
} xmltv_channel_t;
void xmltv_init(void);
xmltv_channel_t *xmltv_channel_find(const char *id, int create);
xmltv_channel_t *xmltv_channel_find_by_displayname(const char *name);
htsmsg_t *xmltv_list_grabbers(void);
const char *xmltv_get_current_grabber(void);
void xmltv_set_current_grabber(const char *path);
void xmltv_set_grab_interval(int s);
void xmltv_set_grab_enable(int on);
extern struct xmltv_channel_list xmltv_displaylist;
extern uint32_t xmltv_grab_interval;
extern uint32_t xmltv_grab_enabled;
extern pthread_mutex_t xmltv_mutex;
#endif /* EPG_XMLTV_H__ */
#endif