Split service out in a superclass and a per-hw type class

This commit is contained in:
Andreas Öman 2013-03-15 12:45:22 +01:00
parent 3f1d299749
commit eec7d0ebcf
17 changed files with 225 additions and 124 deletions

View file

@ -108,6 +108,7 @@ typedef struct dvb_network {
uint32_t dn_disable_pmt_monitor;
uint32_t dn_autodiscovery;
uint32_t dn_nitoid;
uint32_t dn_skip_checksubscr;
struct th_dvb_adapter_list dn_adapters;
@ -248,7 +249,6 @@ typedef struct th_dvb_adapter {
char *tda_identifier;
uint32_t tda_idleclose;
uint32_t tda_skip_initialscan;
uint32_t tda_skip_checksubscr;
uint32_t tda_qmon;
uint32_t tda_poweroff;
uint32_t tda_sidtochan;

View file

@ -77,7 +77,6 @@ tda_save(th_dvb_adapter_t *tda)
htsmsg_add_str(m, "type", dvb_adaptertype_to_str(tda->tda_fe_type));
htsmsg_add_str(m, "displayname", tda->tda_displayname);
htsmsg_add_u32(m, "idleclose", tda->tda_idleclose);
htsmsg_add_u32(m, "skip_checksubscr", tda->tda_skip_checksubscr);
htsmsg_add_u32(m, "sidtochan", tda->tda_sidtochan);
htsmsg_add_u32(m, "qmon", tda->tda_qmon);
htsmsg_add_u32(m, "poweroff", tda->tda_poweroff);
@ -151,25 +150,6 @@ dvb_adapter_set_idleclose(th_dvb_adapter_t *tda, int on)
tda_save(tda);
}
/**
*
*/
void
dvb_adapter_set_skip_checksubscr(th_dvb_adapter_t *tda, int on)
{
if(tda->tda_skip_checksubscr == on)
return;
lock_assert(&global_lock);
tvhlog(LOG_NOTICE, "dvb", "Adapter \"%s\" skip service availability check when mapping set to: %s",
tda->tda_displayname, on ? "On" : "Off");
tda->tda_skip_checksubscr = on;
tda_save(tda);
}
/**
*
*/
@ -609,7 +589,6 @@ dvb_adapter_init(uint32_t adapter_mask, const char *rawfile)
tda->tda_displayname = strdup(name);
htsmsg_get_u32(c, "idleclose", &tda->tda_idleclose);
htsmsg_get_u32(c, "skip_checksubscr", &tda->tda_skip_checksubscr);
htsmsg_get_u32(c, "sidtochan", &tda->tda_sidtochan);
htsmsg_get_u32(c, "qmon", &tda->tda_qmon);
htsmsg_get_u32(c, "poweroff", &tda->tda_poweroff);

View file

@ -65,7 +65,7 @@ static const idclass_t dvb_mux_class = {
.ic_class = "dvbmux",
.ic_get_title = dvb_mux_get_title,
.ic_get_childs = dvb_mux_get_childs,
.ic_properties = {
.ic_properties = (const property_t[]){
{
"enabled", "Enabled", PT_BOOL,
offsetof(dvb_mux_t, dm_enabled)

View file

@ -32,7 +32,7 @@ static idnode_t **dvb_network_get_childs(struct idnode *self);
static const idclass_t dvb_network_class = {
.ic_class = "dvbnetwork",
.ic_get_childs = dvb_network_get_childs,
.ic_properties = {
.ic_properties = (const property_t[]){
{
"autodiscovery", "Auto discovery", PT_BOOL,
offsetof(dvb_network_t, dn_autodiscovery)
@ -42,6 +42,9 @@ static const idclass_t dvb_network_class = {
}, {
"disable_pmt_monitor", "Disable PMT monitor", PT_BOOL,
offsetof(dvb_network_t, dn_disable_pmt_monitor)
}, {
"disable_pmt_monitor", "Disable PMT monitor", PT_BOOL,
offsetof(dvb_network_t, dn_disable_pmt_monitor)
}, {
}},
};
@ -122,16 +125,12 @@ dvb_network_load(htsmsg_t *m, const char *uuid)
if(dn == NULL)
return;
htsmsg_get_u32(m, "autodiscovery", &dn->dn_autodiscovery);
htsmsg_get_u32(m, "nitoid", &dn->dn_nitoid);
htsmsg_get_u32(m, "disable_pmt_monitor", &dn->dn_disable_pmt_monitor);
prop_write_values(dn, dvb_network_class.ic_properties, m);
dvb_mux_load(dn);
dvb_network_schedule_initial_scan(dn);
}
#if 1
/**
*
*/
@ -142,17 +141,12 @@ dvb_network_save(dvb_network_t *dn)
lock_assert(&global_lock);
htsmsg_add_u32(m, "fetype", dn->dn_fe_type);
htsmsg_add_u32(m, "autodiscovery", dn->dn_autodiscovery);
htsmsg_add_u32(m, "nitoid", dn->dn_nitoid);
htsmsg_add_u32(m, "disable_pmt_monitor", dn->dn_disable_pmt_monitor);
prop_read_values(dn, dvb_network_class.ic_properties, m);
hts_settings_save(m, "dvb/networks/%s/config",
idnode_uuid_as_str(&dn->dn_id));
htsmsg_destroy(m);
}
#endif
/**

View file

@ -44,7 +44,20 @@
#include "dvb_support.h"
#include "notify.h"
static htsmsg_t *dvb_service_serialize(service_t *s);
static const char *dvb_service_get_title(struct idnode *self);
const idclass_t dvb_service_class = {
.ic_super = &service_class,
.ic_class = "dvbservice",
.ic_get_title = dvb_service_get_title,
// .ic_get_childs = dvb_service_get_childs,
.ic_properties = (const property_t[]){
{
"dvb_eit_enable", "Use EPG", PT_BOOL,
offsetof(service_t, s_dvb_eit_enable)
}, {
}}
};
/**
@ -385,7 +398,8 @@ dvb_service_find2(dvb_mux_t *dm, uint16_t sid, int pmt_pid,
tvhlog(LOG_DEBUG, "dvb", "Add service \"0x%x\" on \"%s\"", sid,
dvb_mux_nicename(dm));
t = service_create(uuid, S_MPEG_TS);
t = service_create(uuid, S_MPEG_TS, &dvb_service_class);
if (save) *save = 1;
t->s_dvb_service_id = sid;
@ -397,7 +411,6 @@ dvb_service_find2(dvb_mux_t *dm, uint16_t sid, int pmt_pid,
t->s_config_save = dvb_service_save;
t->s_setsourceinfo = dvb_service_setsourceinfo;
t->s_grace_period = dvb_grace_period;
t->s_serialize = dvb_service_serialize;
t->s_enlist = dvb_service_enlist;
t->s_dvb_mux = dm;
@ -409,7 +422,7 @@ dvb_service_find2(dvb_mux_t *dm, uint16_t sid, int pmt_pid,
return t;
}
#if 0
/**
*
*/
@ -454,6 +467,25 @@ dvb_service_serialize(service_t *s)
return m;
}
#endif
/**
*
*/
static const char *
dvb_service_get_title(struct idnode *self)
{
service_t *s = (service_t *)self;
static char buf[100];
if(s->s_svcname) {
return s->s_svcname;
} else {
snprintf(buf, sizeof(buf), "Service-0x%04x", s->s_dvb_service_id);
return buf;
}
}
/**

View file

@ -136,14 +136,22 @@ idnode_uuid_as_str(const idnode_t *in)
/**
*
*/
idnode_t *
idnode_find(const char *uuid)
void *
idnode_find(const char *uuid, const idclass_t *idc)
{
idnode_t skel, *r;
if(hex2bin(skel.in_uuid, 16, uuid))
return NULL;
r = RB_FIND(&idnodes, &skel, in_link, in_cmp);
if(r != NULL && idc != NULL) {
const idclass_t *c = r->in_class;
for(;c != NULL; c = c->ic_super) {
if(idc == c)
return r;
}
return NULL;
}
return r;
}
@ -171,13 +179,23 @@ idnode_serialize(struct idnode *self)
} else {
m = htsmsg_create_map();
htsmsg_t *p = htsmsg_create_map();
htsmsg_t *pn = htsmsg_create_map();
if(c->ic_get_title != NULL) {
htsmsg_add_str(m, "text", c->ic_get_title(self));
} else {
htsmsg_add_str(m, "text", idnode_uuid_as_str(self));
}
htsmsg_add_msg(m, "properties", prop_get_values(self, c->ic_properties));
htsmsg_add_msg(m, "propertynames", prop_get_names(c->ic_properties));
for(;c != NULL; c = c->ic_super) {
prop_read_values(self, c->ic_properties, p);
prop_read_names(c->ic_properties, pn);
}
htsmsg_add_msg(m, "properties", p);
htsmsg_add_msg(m, "propertynames", pn);
htsmsg_add_str(m, "id", idnode_uuid_as_str(self));
}
return m;

View file

@ -7,11 +7,12 @@ struct htsmsg;
struct idnode;
typedef struct idclass {
const struct idclass *ic_super;
const char *ic_class;
struct htsmsg *(*ic_serialize)(struct idnode *self);
struct idnode **(*ic_get_childs)(struct idnode *self);
const char *(*ic_get_title)(struct idnode *self);
const property_t ic_properties[];
const property_t *ic_properties;
} idclass_t;
@ -27,7 +28,7 @@ int idnode_insert(idnode_t *in, const char *uuid, const idclass_t *class);
const char *idnode_uuid_as_str(const idnode_t *in);
idnode_t *idnode_find(const char *uuid);
void *idnode_find(const char *uuid, const idclass_t *class);
void idnode_unlink(idnode_t *in);

View file

@ -48,6 +48,11 @@ static pthread_mutex_t iptv_recvmutex;
struct service_list iptv_all_services; /* All IPTV services */
static struct service_list iptv_active_services; /* Currently enabled */
const idclass_t iptv_class = {
.ic_super = &service_class,
.ic_class = "iptv",
};
/**
* PAT parser. We only parse a single program. CRC has already been verified
*/
@ -496,32 +501,19 @@ iptv_service_dtor(service_t *t)
service_t *
iptv_service_find(const char *id, int create)
{
static int tally;
service_t *t;
char buf[20];
if(id != NULL) {
if(strncmp(id, "iptv_", 5))
return NULL;
LIST_FOREACH(t, &iptv_all_services, s_group_link)
if(!strcmp(t->s_nicename, id)) // XXX(dvbreorg)
return t;
t = idnode_find(id, &iptv_class);
if(t != NULL)
return t;
}
if(create == 0)
return NULL;
if(id == NULL) {
tally++;
snprintf(buf, sizeof(buf), "iptv_%d", tally);
id = buf;
} else {
tally = MAX(atoi(id + 5), tally);
}
t = service_create(id, S_MPEG_TS);
t = service_create(id, S_MPEG_TS, &iptv_class);
t->s_servicetype = ST_SDTV;
t->s_start_feed = iptv_service_start;

View file

@ -1,47 +1,91 @@
#include <stdio.h>
#include <string.h>
#include "tvheadend.h"
#include "prop.h"
#if 0
static const property_t *
prop_find(const property_t *p, const char *id)
{
int i;
for(;p[i].id; i++)
if(!strcmp(id, p[i].id))
return p;
return NULL;
}
#define TO_FROM(x, y) ((x) << 16 | (y))
/**
*
*/
void
prop_write_values(void *ptr, const property_t p[], htsmsg_t *m)
prop_write_values(void *obj, const property_t *pl, htsmsg_t *m)
{
int i = 0;
for(;p[i].id; i++) {
switch(p[i].type) {
case PT_BOOL:
htsmsg_add_bool(m, p[i].id, *(int *)(ptr + p[i].off));
htsmsg_field_t *f;
HTSMSG_FOREACH(f, m) {
if(f->hmf_name == NULL)
continue;
const property_t *p = prop_find(pl, f->hmf_name);
if(p == NULL) {
fprintf(stderr, "Property %s unmappable\n", f->hmf_name);
continue;
}
void *val = obj + p->off;
switch(TO_FROM(p->type, f->hmf_type)) {
case TO_FROM(PT_BOOL, HMF_BOOL):
*(int *)val = f->hmf_bool;
break;
case PT_INT:
htsmsg_add_s32(m, p[i].id, *(int *)(ptr + p[i].off));
case TO_FROM(PT_BOOL, HMF_S64):
*(int *)val = !!f->hmf_s64;
break;
case PT_STR:
htsmsg_add_str(m, p[i].id, (const char *)(ptr + p[i].off));
case TO_FROM(PT_INT, HMF_S64):
*(int *)val = f->hmf_s64;
break;
case TO_FROM(PT_STR, HMF_STR):
if(p->str_set != NULL)
p->str_set(obj, f->hmf_str);
else
mystrset(val, f->hmf_str);
break;
}
}
}
#endif
/**
*
*/
void
prop_read_values(void *ptr, const property_t p[], htsmsg_t *m)
prop_read_values(void *obj, const property_t *p, htsmsg_t *m)
{
const char *s;
if(p == NULL)
return;
int i = 0;
for(;p[i].id; i++) {
void *val = obj + p[i].off;
switch(p[i].type) {
case PT_BOOL:
htsmsg_add_bool(m, p[i].id, *(int *)(ptr + p[i].off));
htsmsg_add_bool(m, p[i].id, *(int *)val);
break;
case PT_INT:
htsmsg_add_s32(m, p[i].id, *(int *)(ptr + p[i].off));
htsmsg_add_s32(m, p[i].id, *(int *)val);
break;
case PT_STR:
htsmsg_add_str(m, p[i].id, (const char *)(ptr + p[i].off));
if(p->str_get != NULL)
s = p->str_get(obj);
else
s = *(const char **)val;
if(s != NULL)
htsmsg_add_str(m, p[i].id, s);
break;
}
}
@ -52,7 +96,7 @@ prop_read_values(void *ptr, const property_t p[], htsmsg_t *m)
*
*/
htsmsg_t *
prop_get_values(void *ptr, const property_t p[])
prop_get_values(void *ptr, const property_t *p)
{
htsmsg_t *m = htsmsg_create_map();
prop_read_values(ptr, p, m);
@ -64,10 +108,12 @@ prop_get_values(void *ptr, const property_t p[])
*
*/
void
prop_read_names(const property_t p[], htsmsg_t *m)
prop_read_names(const property_t *p, htsmsg_t *m)
{
if(p == NULL)
return;
int i = 0;
for(;p[i].name; i++)
for(;p[i].id; i++)
htsmsg_add_str(m, p[i].id, p[i].name);
}
@ -76,7 +122,7 @@ prop_read_names(const property_t p[], htsmsg_t *m)
*
*/
htsmsg_t *
prop_get_names(const property_t p[])
prop_get_names(const property_t *p)
{
htsmsg_t *m = htsmsg_create_map();
prop_read_names(p, m);

View file

@ -14,11 +14,16 @@ typedef struct property {
const char *name;
prop_type_t type;
size_t off;
const char *(*str_get)(void *ptr);
void (*str_set)(void *ptr, const char *str);
} property_t;
void prop_read_values(void *ptr, const property_t p[], htsmsg_t *m);
htsmsg_t *prop_get_values(void *ptr, const property_t p[]);
void prop_read_names(const property_t p[], htsmsg_t *m);
htsmsg_t *prop_get_names(const property_t p[]);
void prop_read_values(void *ptr, const property_t *p, htsmsg_t *m);
htsmsg_t *prop_get_values(void *ptr, const property_t *p);
void prop_read_names(const property_t *p, htsmsg_t *m);
htsmsg_t *prop_get_names(const property_t *p);
void prop_write_values(void *ptr, const property_t *pl, htsmsg_t *m);

View file

@ -48,6 +48,11 @@ typedef struct rawts {
} rawts_t;
const idclass_t rawts_class = {
.ic_super = &service_class,
.ic_class = "rawts",
};
/**
*
*/
@ -112,7 +117,7 @@ rawts_service_add(rawts_t *rt, uint16_t sid, int pmt_pid)
snprintf(tmp, sizeof(tmp), "%s_%04x", rt->rt_identifier, sid);
t = service_create(tmp, S_MPEG_TS);
t = service_create(NULL, S_MPEG_TS, &rawts_class);
t->s_flags |= S_DEBUG;
t->s_dvb_service_id = sid;

View file

@ -50,12 +50,23 @@
#include "lang_codes.h"
static void service_data_timeout(void *aux);
static const char *service_channel_get(void *obj);
static void service_channel_set(void *obj, const char *str);
static htsmsg_t *service_serialize(struct idnode *self);
static const idclass_t service_class = {
const idclass_t service_class = {
.ic_class = "service",
.ic_serialize = service_serialize,
.ic_properties = (const property_t[]){
{
"channel", "Channel", PT_STR,
.str_get = service_channel_get,
.str_set = service_channel_set,
}, {
"enabled", "Enabled", PT_BOOL,
offsetof(service_t, s_enabled)
}, {
}}
};
/**
@ -70,7 +81,7 @@ stream_init(elementary_stream_t *st)
st->es_curdts = PTS_UNSET;
st->es_curpts = PTS_UNSET;
st->es_prevdts = PTS_UNSET;
st->es_pcr_real_last = PTS_UNSET;
st->es_pcr_last = PTS_UNSET;
st->es_pcr_drift = 0;
@ -466,7 +477,7 @@ service_destroy(service_t *t)
* Create and initialize a new service struct
*/
service_t *
service_create(const char *uuid, int source_type)
service_create(const char *uuid, int source_type, const idclass_t *idc)
{
service_t *t = calloc(1, sizeof(service_t));
@ -486,7 +497,7 @@ service_create(const char *uuid, int source_type)
streaming_pad_init(&t->s_streaming_pad);
idnode_insert(&t->s_id, uuid, &service_class);
idnode_insert(&t->s_id, uuid, idc);
return t;
}
@ -497,8 +508,7 @@ service_create(const char *uuid, int source_type)
service_t *
service_find_by_identifier(const char *identifier)
{
idnode_t *id = idnode_find(identifier);
return id->in_class == &service_class ? (service_t *)id : NULL;
return idnode_find(identifier, &service_class);
}
@ -648,6 +658,27 @@ service_map_channel(service_t *t, channel_t *ch, int save)
t->s_config_save(t);
}
/**
*
*/
static const char *service_channel_get(void *obj)
{
service_t *s = obj;
return s->s_ch ? s->s_ch->ch_name : NULL;
}
/**
*
*/
static void
service_channel_set(void *obj, const char *str)
{
service_map_channel(obj, str ? channel_find_by_name(str, 1, 0) : NULL, 1);
}
/**
*
*/
@ -1187,14 +1218,3 @@ htsmsg_t *servicetype_list ( void )
}
return ret;
}
/**
*
*/
static htsmsg_t *
service_serialize(struct idnode *self)
{
service_t *s = (service_t *)self;
return s->s_serialize(s);
}

View file

@ -25,6 +25,8 @@
#include "idnode.h"
extern const idclass_t service_class;
/**
* Descrambler superclass
*
@ -315,8 +317,6 @@ typedef struct service {
void (*s_dtor)(struct service *t);
htsmsg_t *(*s_serialize)(struct service *s);
/*
* Per source type structs
*/
@ -551,7 +551,7 @@ void service_init(void);
int service_start(service_t *t, int instance);
service_t *service_create(const char *uuid, int source_type);
service_t *service_create(const char *uuid, int source_type, const idclass_t *idc);
void service_unref(service_t *t);

View file

@ -109,7 +109,7 @@ serviceprobe_thread(void *aux)
}
// XXX(dvbreorg)
checksubscr = 1; // !t->s_dvb_mux->tdmi_adapter->tda_skip_checksubscr;
checksubscr = !t->s_dvb_mux->dm_dn->dn_skip_checksubscr;
if (checksubscr) {
tvhlog(LOG_INFO, "serviceprobe", "%20s: checking...",

View file

@ -27,6 +27,7 @@
#include <netinet/in.h>
#include <sys/time.h>
#include <libgen.h>
#include <string.h>
#include "queue.h"
#include "avg.h"
@ -441,6 +442,12 @@ static inline const char *tvh_strbegins(const char *s1, const char *s2)
return s1;
}
static inline void mystrset(char **p, const char *s)
{
free(*p);
*p = s ? strdup(s) : NULL;
}
int tvh_open(const char *pathname, int flags, mode_t mode);
int tvh_socket(int domain, int type, int protocol);

View file

@ -45,6 +45,10 @@ struct v4l_adapter_queue v4l_adapters;
static void v4l_adapter_notify(v4l_adapter_t *va);
const idclass_t v4l_class = {
.ic_super = &service_class,
.ic_class = "v4l",
};
/**
*
@ -354,7 +358,7 @@ v4l_service_find(v4l_adapter_t *va, const char *id, int create)
va->va_tally = MAX(atoi(id + vaidlen + 1), va->va_tally);
}
t = service_create(id, 0);
t = service_create(id, 0, &v4l_class);
t->s_start_feed = v4l_service_start;
t->s_refresh_feed = v4l_service_refresh;

View file

@ -151,7 +151,6 @@ extjs_dvbadapter(http_connection_t *hc, const char *remain, void *opaque)
htsmsg_add_str(r, "name", tda->tda_displayname);
htsmsg_add_u32(r, "skip_initialscan", tda->tda_skip_initialscan);
htsmsg_add_u32(r, "idleclose", tda->tda_idleclose);
htsmsg_add_u32(r, "skip_checksubscr", tda->tda_skip_checksubscr);
htsmsg_add_u32(r, "qmon", tda->tda_qmon);
htsmsg_add_u32(r, "poweroff", tda->tda_poweroff);
htsmsg_add_u32(r, "sidtochan", tda->tda_sidtochan);
@ -177,9 +176,6 @@ extjs_dvbadapter(http_connection_t *hc, const char *remain, void *opaque)
s = http_arg_get(&hc->hc_req_args, "idleclose");
dvb_adapter_set_idleclose(tda, !!s);
s = http_arg_get(&hc->hc_req_args, "skip_checksubscr");
dvb_adapter_set_skip_checksubscr(tda, !!s);
s = http_arg_get(&hc->hc_req_args, "qmon");
dvb_adapter_set_qmon(tda, !!s);
@ -708,17 +704,19 @@ extjs_dvbnetworks(http_connection_t *hc, const char *remain, void *opaque)
if(!strcmp(s, "root")) {
v = dvb_network_root();
} else {
idnode_t *n = idnode_find(s);
v = n != NULL && n->in_class->ic_get_childs != NULL ?
idnode_t *n = idnode_find(s, NULL);
v = n != NULL && n->in_class->ic_get_childs != NULL ?
n->in_class->ic_get_childs(n) : NULL;
}
int i;
for(i = 0; v[i] != NULL; i++) {
htsmsg_t *m = idnode_serialize(v[i]);
if(v[i]->in_class->ic_get_childs == NULL)
htsmsg_add_u32(m, "leaf", 1);
htsmsg_add_msg(out, NULL, m);
if(v != NULL) {
int i;
for(i = 0; v[i] != NULL; i++) {
htsmsg_t *m = idnode_serialize(v[i]);
if(v[i]->in_class->ic_get_childs == NULL)
htsmsg_add_u32(m, "leaf", 1);
htsmsg_add_msg(out, NULL, m);
}
}
pthread_mutex_unlock(&global_lock);