Start work on epg load/save and also added back in initial xmltv parser.
This commit is contained in:
parent
a78994729e
commit
988eb8133a
7 changed files with 335 additions and 897 deletions
4
Makefile
4
Makefile
|
@ -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
170
src/epg.c
|
@ -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
|
||||
* *************************************************************************/
|
||||
|
|
19
src/epg.h
19
src/epg.h
|
@ -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
|
||||
* ***********************************************************************/
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue