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;
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;
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);
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);
-}
-
/**
*
*/
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);
.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)
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)
}, {
"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)
}, {
}},
};
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
+
/**
*
*/
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
-
/**
#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)
+ }, {
+ }}
+};
/**
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;
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;
return t;
}
-
+#if 0
/**
*
*/
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;
+ }
+}
/**
/**
*
*/
-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;
}
} 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;
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;
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);
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
*/
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;
+#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;
}
}
*
*/
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);
*
*/
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);
}
*
*/
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);
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);
} rawts_t;
+const idclass_t rawts_class = {
+ .ic_super = &service_class,
+ .ic_class = "rawts",
+};
+
/**
*
*/
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;
#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)
+ }, {
+ }}
};
/**
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;
* 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));
streaming_pad_init(&t->s_streaming_pad);
- idnode_insert(&t->s_id, uuid, &service_class);
+ idnode_insert(&t->s_id, uuid, idc);
return t;
}
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);
}
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);
+}
+
+
/**
*
*/
}
return ret;
}
-
-
-/**
- *
- */
-static htsmsg_t *
-service_serialize(struct idnode *self)
-{
- service_t *s = (service_t *)self;
- return s->s_serialize(s);
-}
#include "idnode.h"
+extern const idclass_t service_class;
+
/**
* Descrambler superclass
*
void (*s_dtor)(struct service *t);
- htsmsg_t *(*s_serialize)(struct service *s);
-
/*
* Per source type structs
*/
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);
}
// 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...",
#include <netinet/in.h>
#include <sys/time.h>
#include <libgen.h>
+#include <string.h>
#include "queue.h"
#include "avg.h"
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);
static void v4l_adapter_notify(v4l_adapter_t *va);
+const idclass_t v4l_class = {
+ .ic_super = &service_class,
+ .ic_class = "v4l",
+};
/**
*
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;
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);
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);
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);