Implement updating of properties from webui
This commit is contained in:
parent
f6ce21f747
commit
12a963e839
12 changed files with 454 additions and 176 deletions
|
@ -65,6 +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_save = (void *)dvb_mux_save,
|
||||
.ic_properties = (const property_t[]){
|
||||
{
|
||||
"enabled", "Enabled", PT_BOOL,
|
||||
|
@ -517,6 +518,7 @@ dvb_mux_save(dvb_mux_t *dm)
|
|||
htsmsg_t *m = htsmsg_create_map();
|
||||
|
||||
htsmsg_add_u32(m, "enabled", dm->dm_enabled);
|
||||
htsmsg_add_str(m, "uuid", idnode_uuid_as_str(&dm->dm_id));
|
||||
|
||||
htsmsg_add_u32(m, "transportstreamid", dm->dm_transport_stream_id);
|
||||
htsmsg_add_u32(m, "originalnetworkid", dm->dm_network_id);
|
||||
|
@ -727,14 +729,20 @@ dvb_mux_create_by_msg(dvb_network_t *dn, htsmsg_t *m, const char *fname)
|
|||
if(htsmsg_get_u32(m, "enabled", &enabled))
|
||||
enabled = 1;
|
||||
|
||||
const char *uuid = htsmsg_get_str(m, "uuid");
|
||||
dm = dvb_mux_create(dn, &dmc,
|
||||
onid, tsid, htsmsg_get_str(m, "network"), NULL, enabled,
|
||||
htsmsg_get_u32_or_default(m, "needscan", 1),
|
||||
htsmsg_get_str(m, "uuid"));
|
||||
uuid);
|
||||
if(dm != NULL) {
|
||||
|
||||
if((s = htsmsg_get_str(m, "default_authority")))
|
||||
dm->dm_default_authority = strdup(s);
|
||||
|
||||
|
||||
if(uuid == NULL)
|
||||
// If mux didn't have UUID, write it to make sure UUID is stable
|
||||
dvb_mux_save(dm);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -25,13 +25,24 @@
|
|||
#include "settings.h"
|
||||
#include "dvb_support.h"
|
||||
|
||||
|
||||
const static struct strtab typetab[] = {
|
||||
{"DVB-T", FE_OFDM},
|
||||
{"DVB-C", FE_QAM},
|
||||
{"DVB-S", FE_QPSK},
|
||||
{"ATSC", FE_ATSC},
|
||||
};
|
||||
|
||||
|
||||
struct dvb_network_list dvb_networks;
|
||||
|
||||
static idnode_t **dvb_network_get_childs(struct idnode *self);
|
||||
static void dvb_network_save(idnode_t *in);
|
||||
|
||||
static const idclass_t dvb_network_class = {
|
||||
.ic_class = "dvbnetwork",
|
||||
.ic_get_childs = dvb_network_get_childs,
|
||||
.ic_save = dvb_network_save,
|
||||
.ic_properties = (const property_t[]){
|
||||
{
|
||||
"autodiscovery", "Auto discovery", PT_BOOL,
|
||||
|
@ -42,11 +53,7 @@ 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)
|
||||
}, {
|
||||
}},
|
||||
}, {}},
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -116,15 +123,19 @@ dvb_network_get_childs(struct idnode *self)
|
|||
static void
|
||||
dvb_network_load(htsmsg_t *m, const char *uuid)
|
||||
{
|
||||
uint32_t fetype;
|
||||
const char *s = htsmsg_get_str(m, "type");
|
||||
if(s == NULL)
|
||||
return;
|
||||
|
||||
if(htsmsg_get_u32(m, "fetype", &fetype))
|
||||
int fetype = str2val(s, typetab);
|
||||
if(fetype == -1)
|
||||
return;
|
||||
|
||||
dvb_network_t *dn = dvb_network_create(fetype, uuid);
|
||||
if(dn == NULL)
|
||||
return;
|
||||
|
||||
htsmsg_delete_field(m, "type");
|
||||
prop_write_values(dn, dvb_network_class.ic_properties, m);
|
||||
dvb_mux_load(dn);
|
||||
dvb_network_schedule_initial_scan(dn);
|
||||
|
@ -135,16 +146,19 @@ dvb_network_load(htsmsg_t *m, const char *uuid)
|
|||
*
|
||||
*/
|
||||
static void
|
||||
dvb_network_save(dvb_network_t *dn)
|
||||
dvb_network_save(idnode_t *in)
|
||||
{
|
||||
dvb_network_t *dn = (dvb_network_t *)in;
|
||||
htsmsg_t *m = htsmsg_create_map();
|
||||
|
||||
lock_assert(&global_lock);
|
||||
|
||||
prop_read_values(dn, dvb_network_class.ic_properties, m);
|
||||
htsmsg_add_str(m, "type", val2str(dn->dn_fe_type, typetab));
|
||||
prop_read_values(in, dvb_network_class.ic_properties, m);
|
||||
|
||||
hts_settings_save(m, "dvb/networks/%s/config",
|
||||
idnode_uuid_as_str(&dn->dn_id));
|
||||
idnode_uuid_as_str(in));
|
||||
|
||||
htsmsg_destroy(m);
|
||||
}
|
||||
|
||||
|
@ -185,11 +199,6 @@ dvb_network_init(void)
|
|||
htsmsg_t *l, *c;
|
||||
htsmsg_field_t *f;
|
||||
|
||||
if(0) {
|
||||
dvb_network_save(dvb_network_create(FE_QAM, NULL));
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if((l = hts_settings_load_r(1, "dvb/networks")) == NULL)
|
||||
return;
|
||||
|
||||
|
|
|
@ -175,6 +175,7 @@ dvb_service_save(service_t *t)
|
|||
|
||||
lock_assert(&global_lock);
|
||||
|
||||
htsmsg_add_str(m, "uuid", idnode_uuid_as_str(&t->s_id));
|
||||
htsmsg_add_u32(m, "service_id", t->s_dvb_service_id);
|
||||
htsmsg_add_u32(m, "pmt", t->s_pmt_pid);
|
||||
htsmsg_add_u32(m, "stype", t->s_servicetype);
|
||||
|
@ -246,7 +247,8 @@ dvb_service_load(dvb_mux_t *dm)
|
|||
if(htsmsg_get_u32(c, "pmt", &pmt))
|
||||
continue;
|
||||
|
||||
t = dvb_service_find(dm, sid, pmt, f->hmf_name);
|
||||
const char *uuid = htsmsg_get_str(c, "uuid");
|
||||
t = dvb_service_find(dm, sid, pmt, uuid);
|
||||
|
||||
htsmsg_get_u32(c, "stype", &t->s_servicetype);
|
||||
if(htsmsg_get_u32(c, "scrambled", &u32))
|
||||
|
@ -285,6 +287,12 @@ dvb_service_load(dvb_mux_t *dm)
|
|||
|
||||
if(s && u32)
|
||||
service_map_channel(t, channel_find_by_name(s, 1, 0), 0);
|
||||
|
||||
if(uuid == NULL) {
|
||||
// If service config on disk lacked UUID (for whatever reason),
|
||||
// write it back
|
||||
dvb_service_save(t);
|
||||
}
|
||||
}
|
||||
htsmsg_destroy(l);
|
||||
}
|
||||
|
@ -422,53 +430,6 @@ dvb_service_find2(dvb_mux_t *dm, uint16_t sid, int pmt_pid,
|
|||
return t;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/**
|
||||
*
|
||||
*/
|
||||
static htsmsg_t *
|
||||
dvb_service_serialize(service_t *s)
|
||||
{
|
||||
dvb_mux_t *dm = s->s_dvb_mux;
|
||||
htsmsg_t *m = htsmsg_create_map();
|
||||
char buf[100];
|
||||
|
||||
if(s->s_svcname) {
|
||||
htsmsg_add_str(m, "text", s->s_svcname);
|
||||
} else {
|
||||
snprintf(buf, sizeof(buf), "Service-0x%04x",
|
||||
s->s_dvb_service_id);
|
||||
htsmsg_add_str(m, "text", buf);
|
||||
}
|
||||
|
||||
htsmsg_add_u32(m, "enabled", s->s_enabled);
|
||||
htsmsg_add_u32(m, "channel", s->s_channel_number);
|
||||
|
||||
htsmsg_add_u32(m, "sid", s->s_dvb_service_id);
|
||||
htsmsg_add_u32(m, "pmt", s->s_pmt_pid);
|
||||
htsmsg_add_u32(m, "pcr", s->s_pcr_pid);
|
||||
|
||||
htsmsg_add_str(m, "type", service_servicetype_txt(s));
|
||||
|
||||
htsmsg_add_str(m, "svcname", s->s_svcname ?: "");
|
||||
htsmsg_add_str(m, "provider", s->s_provider ?: "");
|
||||
|
||||
htsmsg_add_str(m, "network", dm->dm_network_name ?: "");
|
||||
|
||||
htsmsg_add_str(m, "mux", dvb_mux_nicefreq(dm));
|
||||
|
||||
if(s->s_ch != NULL)
|
||||
htsmsg_add_str(m, "channelname", s->s_ch->ch_name);
|
||||
|
||||
if(s->s_dvb_charset != NULL)
|
||||
htsmsg_add_str(m, "dvb_charset", s->s_dvb_charset);
|
||||
|
||||
htsmsg_add_u32(m, "dvb_eit_enable", s->s_dvb_eit_enable);
|
||||
|
||||
return m;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
|
|
85
src/idnode.c
85
src/idnode.c
|
@ -166,6 +166,27 @@ idnode_unlink(idnode_t *in)
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Recursive to get superclass nodes first
|
||||
*/
|
||||
static void
|
||||
add_descriptors(struct idnode *self, const idclass_t *ic, htsmsg_t *p)
|
||||
{
|
||||
if(ic->ic_super != NULL)
|
||||
add_descriptors(self, ic->ic_super, p);
|
||||
|
||||
if(TAILQ_FIRST(&p->hm_fields) != NULL) {
|
||||
// Only add separator if not empty
|
||||
htsmsg_t *m = htsmsg_create_map();
|
||||
htsmsg_add_str(m, "caption", ic->ic_caption ?: ic->ic_class);
|
||||
htsmsg_add_str(m, "type", "separator");
|
||||
htsmsg_add_msg(p, NULL, m);
|
||||
}
|
||||
|
||||
prop_add_descriptors_to_msg(self, ic->ic_properties, p);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
@ -179,24 +200,70 @@ 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));
|
||||
}
|
||||
|
||||
for(;c != NULL; c = c->ic_super) {
|
||||
prop_read_values(self, c->ic_properties, p);
|
||||
prop_read_names(c->ic_properties, pn);
|
||||
}
|
||||
htsmsg_t *p = htsmsg_create_list();
|
||||
add_descriptors(self, c, p);
|
||||
|
||||
htsmsg_add_msg(m, "properties", p);
|
||||
htsmsg_add_msg(m, "propertynames", pn);
|
||||
htsmsg_add_msg(m, "descriptors", p);
|
||||
|
||||
htsmsg_add_str(m, "id", idnode_uuid_as_str(self));
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
static void
|
||||
idnode_save(idnode_t *in)
|
||||
{
|
||||
const idclass_t *ic = in->in_class;
|
||||
for(; ic != NULL; ic = ic->ic_super) {
|
||||
if(ic->ic_save != NULL) {
|
||||
ic->ic_save(in);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
void
|
||||
idnode_set_prop(idnode_t *in, const char *key, const char *value)
|
||||
{
|
||||
const idclass_t *ic = in->in_class;
|
||||
int do_save = 0;
|
||||
for(;ic != NULL; ic = ic->ic_super) {
|
||||
int x = prop_set(in, ic->ic_properties, key, value);
|
||||
if(x == -1)
|
||||
continue;
|
||||
do_save |= x;
|
||||
break;
|
||||
}
|
||||
if(do_save)
|
||||
idnode_save(in);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
void
|
||||
idnode_update_all_props(idnode_t *in,
|
||||
const char *(*getvalue)(void *opaque, const char *key),
|
||||
void *opaque)
|
||||
{
|
||||
const idclass_t *ic = in->in_class;
|
||||
int do_save = 0;
|
||||
for(;ic != NULL; ic = ic->ic_super)
|
||||
do_save |= prop_update_all(in, ic->ic_properties, getvalue, opaque);
|
||||
if(do_save)
|
||||
idnode_save(in);
|
||||
}
|
||||
|
|
|
@ -9,9 +9,11 @@ struct idnode;
|
|||
typedef struct idclass {
|
||||
const struct idclass *ic_super;
|
||||
const char *ic_class;
|
||||
const char *ic_caption;
|
||||
struct htsmsg *(*ic_serialize)(struct idnode *self);
|
||||
struct idnode **(*ic_get_childs)(struct idnode *self);
|
||||
const char *(*ic_get_title)(struct idnode *self);
|
||||
void (*ic_save)(struct idnode *self);
|
||||
const property_t *ic_properties;
|
||||
} idclass_t;
|
||||
|
||||
|
@ -33,3 +35,10 @@ void *idnode_find(const char *uuid, const idclass_t *class);
|
|||
void idnode_unlink(idnode_t *in);
|
||||
|
||||
htsmsg_t *idnode_serialize(struct idnode *self);
|
||||
|
||||
void idnode_set_prop(idnode_t *in, const char *key, const char *value);
|
||||
|
||||
void idnode_update_all_props(idnode_t *in,
|
||||
const char *(*getvalue)(void *opaque,
|
||||
const char *key),
|
||||
void *opaque);
|
||||
|
|
184
src/prop.c
184
src/prop.c
|
@ -7,13 +7,33 @@
|
|||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
static int
|
||||
str_to_bool(const char *s)
|
||||
{
|
||||
if(s == NULL)
|
||||
return 0;
|
||||
int v = atoi(s);
|
||||
if(v)
|
||||
return 1;
|
||||
if(!strcasecmp(s, "on") ||
|
||||
!strcasecmp(s, "true") ||
|
||||
!strcasecmp(s, "yes"))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static const property_t *
|
||||
prop_find(const property_t *p, const char *id)
|
||||
{
|
||||
int i;
|
||||
int i = 0;
|
||||
for(;p[i].id; i++)
|
||||
if(!strcmp(id, p[i].id))
|
||||
return p;
|
||||
return p + i;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -63,68 +83,142 @@ prop_write_values(void *obj, const property_t *pl, htsmsg_t *m)
|
|||
/**
|
||||
*
|
||||
*/
|
||||
void
|
||||
prop_read_values(void *obj, const property_t *p, htsmsg_t *m)
|
||||
static void
|
||||
prop_read_value(void *obj, const property_t *p, htsmsg_t *m, const char *name)
|
||||
{
|
||||
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 *)val);
|
||||
break;
|
||||
case PT_INT:
|
||||
htsmsg_add_s32(m, p[i].id, *(int *)val);
|
||||
break;
|
||||
case PT_STR:
|
||||
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;
|
||||
}
|
||||
const void *val = obj + p->off;
|
||||
|
||||
switch(p->type) {
|
||||
case PT_BOOL:
|
||||
htsmsg_add_bool(m, name, *(int *)val);
|
||||
break;
|
||||
case PT_INT:
|
||||
htsmsg_add_s32(m, name, *(int *)val);
|
||||
break;
|
||||
case PT_STR:
|
||||
if(p->str_get != NULL)
|
||||
s = p->str_get(obj);
|
||||
else
|
||||
s = *(const char **)val;
|
||||
if(s != NULL)
|
||||
htsmsg_add_str(m, name, s);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
htsmsg_t *
|
||||
prop_get_values(void *ptr, const property_t *p)
|
||||
{
|
||||
htsmsg_t *m = htsmsg_create_map();
|
||||
prop_read_values(ptr, p, m);
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
void
|
||||
prop_read_names(const property_t *p, htsmsg_t *m)
|
||||
prop_read_values(void *obj, const property_t *p, htsmsg_t *m)
|
||||
{
|
||||
if(p == NULL)
|
||||
return;
|
||||
int i = 0;
|
||||
for(;p[i].id; i++)
|
||||
htsmsg_add_str(m, p[i].id, p[i].name);
|
||||
prop_read_value(obj, p+i, m, p[i].id);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
htsmsg_t *
|
||||
prop_get_names(const property_t *p)
|
||||
const static struct strtab typetab[] = {
|
||||
{ "bool", PT_BOOL },
|
||||
{ "int", PT_INT },
|
||||
{ "str", PT_STR },
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
void
|
||||
prop_add_descriptors_to_msg(void *obj, const property_t *p, htsmsg_t *msg)
|
||||
{
|
||||
htsmsg_t *m = htsmsg_create_map();
|
||||
prop_read_names(p, m);
|
||||
return m;
|
||||
if(p == NULL)
|
||||
return;
|
||||
int i = 0;
|
||||
for(;p[i].id; i++) {
|
||||
htsmsg_t *m = htsmsg_create_map();
|
||||
htsmsg_add_str(m, "id", p[i].id);
|
||||
htsmsg_add_str(m, "caption", p[i].name);
|
||||
htsmsg_add_str(m, "type", val2str(p[i].type, typetab) ?: "unknown");
|
||||
prop_read_value(obj, p+i, m, "value");
|
||||
htsmsg_add_msg(msg, NULL, m);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* value can be NULL
|
||||
*
|
||||
* Return 1 if we actually changed something
|
||||
*/
|
||||
static int
|
||||
prop_seti(void *obj, const property_t *p, const char *value)
|
||||
{
|
||||
int i32;
|
||||
const char *s;
|
||||
|
||||
void *val = obj + p->off;
|
||||
switch(p->type) {
|
||||
|
||||
case PT_BOOL:
|
||||
i32 = str_to_bool(value);
|
||||
if(0)
|
||||
case PT_INT:
|
||||
i32 = value ? atoi(value) : 0;
|
||||
if(*(int *)val == i32)
|
||||
return 0; // Already set
|
||||
*(int *)val = i32;
|
||||
break;
|
||||
|
||||
case PT_STR:
|
||||
if(p->str_get != NULL)
|
||||
s = p->str_get(obj);
|
||||
else
|
||||
s = *(const char **)val;
|
||||
|
||||
if(!strcmp(s ?: "", value ?: ""))
|
||||
return 0;
|
||||
|
||||
if(p->str_set != NULL)
|
||||
p->str_set(obj, value);
|
||||
else
|
||||
mystrset(val, value);
|
||||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return 1 if something changed
|
||||
*/
|
||||
int
|
||||
prop_set(void *obj, const property_t *p, const char *key, const char *value)
|
||||
{
|
||||
if((p = prop_find(p, key)) == NULL)
|
||||
return -1;
|
||||
return prop_seti(obj, p, value);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
int
|
||||
prop_update_all(void *obj, const property_t *p,
|
||||
const char *(*getvalue)(void *opaque, const char *key),
|
||||
void *opaque)
|
||||
{
|
||||
int i = 0;
|
||||
int r = 0;
|
||||
for(; p[i].id; i++)
|
||||
r |= prop_seti(obj, p+i, getvalue(opaque, p[i].id));
|
||||
return r;
|
||||
}
|
||||
|
|
14
src/prop.h
14
src/prop.h
|
@ -22,8 +22,14 @@ typedef struct property {
|
|||
|
||||
|
||||
|
||||
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_add_descriptors_to_msg(void *obj, const property_t *p, htsmsg_t *msg);
|
||||
|
||||
void prop_write_values(void *ptr, const property_t *pl, htsmsg_t *m);
|
||||
|
||||
void prop_read_values(void *obj, const property_t *p, htsmsg_t *m);
|
||||
|
||||
int prop_set(void *obj, const property_t *p, const char *key, const char *val);
|
||||
|
||||
int prop_update_all(void *obj, const property_t *p,
|
||||
const char *(*getvalue)(void *opaque, const char *key),
|
||||
void *opaque);
|
||||
|
|
|
@ -52,10 +52,12 @@
|
|||
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 void service_save(struct idnode *self);
|
||||
|
||||
const idclass_t service_class = {
|
||||
.ic_class = "service",
|
||||
.ic_caption = "Service",
|
||||
.ic_save = service_save,
|
||||
.ic_properties = (const property_t[]){
|
||||
{
|
||||
"channel", "Channel", PT_STR,
|
||||
|
@ -675,7 +677,7 @@ static const char *service_channel_get(void *obj)
|
|||
static void
|
||||
service_channel_set(void *obj, const char *str)
|
||||
{
|
||||
service_map_channel(obj, str ? channel_find_by_name(str, 1, 0) : NULL, 1);
|
||||
service_map_channel(obj, str ? channel_find_by_name(str, 1, 0) : NULL, 0);
|
||||
}
|
||||
|
||||
|
||||
|
@ -931,6 +933,16 @@ service_request_save(service_t *t, int restart)
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
static void
|
||||
service_save(struct idnode *self)
|
||||
{
|
||||
service_t *s = (service_t *)self;
|
||||
s->s_config_save(s);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
|
|
@ -1900,6 +1900,103 @@ extjs_config(http_connection_t *hc, const char *remain, void *opaque)
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
int
|
||||
extjs_get_idnode(http_connection_t *hc, const char *remain, void *opaque,
|
||||
idnode_t **(*rootfn)(void))
|
||||
{
|
||||
htsbuf_queue_t *hq = &hc->hc_reply;
|
||||
const char *s = http_arg_get(&hc->hc_req_args, "node");
|
||||
htsmsg_t *out = NULL;
|
||||
|
||||
if(s == NULL)
|
||||
return HTTP_STATUS_BAD_REQUEST;
|
||||
|
||||
pthread_mutex_lock(&global_lock);
|
||||
|
||||
if(http_access_verify(hc, ACCESS_ADMIN)) {
|
||||
pthread_mutex_unlock(&global_lock);
|
||||
return HTTP_STATUS_UNAUTHORIZED;
|
||||
}
|
||||
|
||||
out = htsmsg_create_list();
|
||||
idnode_t **v;
|
||||
|
||||
if(!strcmp(s, "root")) {
|
||||
v = rootfn();
|
||||
} else {
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
free(v);
|
||||
|
||||
htsmsg_json_serialize(out, hq, 0);
|
||||
htsmsg_destroy(out);
|
||||
http_output_content(hc, "text/x-json; charset=UTF-8");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static const char *
|
||||
get_prop_value(void *opaque, const char *key)
|
||||
{
|
||||
http_connection_t *hc = opaque;
|
||||
return http_arg_get(&hc->hc_req_args, key);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
static int
|
||||
extjs_item_update(http_connection_t *hc, const char *remain, void *opaque)
|
||||
{
|
||||
htsbuf_queue_t *hq = &hc->hc_reply;
|
||||
htsmsg_t *out = NULL;
|
||||
|
||||
if(remain == NULL)
|
||||
return HTTP_STATUS_BAD_REQUEST;
|
||||
|
||||
pthread_mutex_lock(&global_lock);
|
||||
|
||||
idnode_t *n = idnode_find(remain, NULL);
|
||||
|
||||
if(n == NULL) {
|
||||
pthread_mutex_unlock(&global_lock);
|
||||
return 404;
|
||||
}
|
||||
|
||||
idnode_update_all_props(n, get_prop_value, hc);
|
||||
|
||||
pthread_mutex_unlock(&global_lock);
|
||||
|
||||
out = htsmsg_create_map();
|
||||
htsmsg_add_u32(out, "success", 1);
|
||||
htsmsg_json_serialize(out, hq, 0);
|
||||
htsmsg_destroy(out);
|
||||
http_output_content(hc, "text/x-json; charset=UTF-8");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* WEB user interface
|
||||
*/
|
||||
|
@ -1926,6 +2023,7 @@ extjs_start(void)
|
|||
http_path_add("/iptv/services", NULL, extjs_iptvservices, ACCESS_ADMIN);
|
||||
http_path_add("/servicedetails", NULL, extjs_servicedetails, ACCESS_ADMIN);
|
||||
http_path_add("/tv/adapter", NULL, extjs_tvadapter, ACCESS_ADMIN);
|
||||
http_path_add("/item/update", NULL, extjs_item_update, ACCESS_ADMIN);
|
||||
|
||||
#if ENABLE_LINUXDVB
|
||||
extjs_start_dvb();
|
||||
|
|
|
@ -684,53 +684,10 @@ extjs_list_dvb_adapters(htsmsg_t *array)
|
|||
static int
|
||||
extjs_dvbnetworks(http_connection_t *hc, const char *remain, void *opaque)
|
||||
{
|
||||
htsbuf_queue_t *hq = &hc->hc_reply;
|
||||
const char *s = http_arg_get(&hc->hc_req_args, "node");
|
||||
htsmsg_t *out = NULL;
|
||||
|
||||
if(s == NULL)
|
||||
return HTTP_STATUS_BAD_REQUEST;
|
||||
|
||||
pthread_mutex_lock(&global_lock);
|
||||
|
||||
if(http_access_verify(hc, ACCESS_ADMIN)) {
|
||||
pthread_mutex_unlock(&global_lock);
|
||||
return HTTP_STATUS_UNAUTHORIZED;
|
||||
}
|
||||
|
||||
out = htsmsg_create_list();
|
||||
idnode_t **v;
|
||||
|
||||
if(!strcmp(s, "root")) {
|
||||
v = dvb_network_root();
|
||||
} else {
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
free(v);
|
||||
|
||||
htsmsg_json_serialize(out, hq, 0);
|
||||
htsmsg_destroy(out);
|
||||
http_output_content(hc, "text/x-json; charset=UTF-8");
|
||||
return 0;
|
||||
return extjs_get_idnode(hc, remain, opaque, &dvb_network_root);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* DVB WEB user interface
|
||||
*/
|
||||
|
|
|
@ -1,14 +1,66 @@
|
|||
|
||||
|
||||
|
||||
tvheadend.item_editor = function(item) {
|
||||
var propsGrid = new Ext.grid.PropertyGrid({
|
||||
flex:1,
|
||||
padding: 5,
|
||||
propertyNames: item.propertynames,
|
||||
source: item.properties
|
||||
|
||||
var fields = []
|
||||
console.log(fields);
|
||||
for (var idx in item.descriptors) {
|
||||
var f = item.descriptors[idx];
|
||||
switch(f.type) {
|
||||
case 'str':
|
||||
fields.push({
|
||||
fieldLabel: f.caption,
|
||||
name: f.id,
|
||||
value: f.value
|
||||
});
|
||||
break;
|
||||
|
||||
case 'bool':
|
||||
fields.push({
|
||||
xtype: 'checkbox',
|
||||
fieldLabel: f.caption,
|
||||
name: f.id,
|
||||
checked: f.value
|
||||
});
|
||||
break;
|
||||
|
||||
case 'separator':
|
||||
fields.push({
|
||||
xtype: 'label',
|
||||
fieldLabel: f.caption,
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
var panel = new Ext.FormPanel({
|
||||
labelWidth: 75, // label settings here cascade unless overridden
|
||||
url:'save-form.php',
|
||||
frame:true,
|
||||
title: 'Parameters',
|
||||
bodyStyle:'padding:5px 5px 0',
|
||||
width: 350,
|
||||
defaults: {width: 230},
|
||||
defaultType: 'textfield',
|
||||
items: fields,
|
||||
|
||||
buttons: [{
|
||||
text: 'Save',
|
||||
handler: function(){
|
||||
if(panel.getForm().isValid()){
|
||||
panel.getForm().submit({
|
||||
url: 'item/update/' + item.id,
|
||||
waitMsg : 'Saving Data...'
|
||||
});
|
||||
}
|
||||
}
|
||||
},{
|
||||
text: 'Reset',
|
||||
handler: function(){
|
||||
panel.getForm().reset();
|
||||
}
|
||||
}]
|
||||
});
|
||||
return propsGrid;
|
||||
return panel;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
#define WEBUI_H_
|
||||
|
||||
#include "htsmsg.h"
|
||||
#include "idnode.h"
|
||||
#include "http.h"
|
||||
|
||||
void webui_init(void);
|
||||
|
||||
|
@ -45,6 +47,9 @@ void extjs_service_update(htsmsg_t *in);
|
|||
void extjs_service_delete(htsmsg_t *in);
|
||||
|
||||
|
||||
int extjs_get_idnode(http_connection_t *hc, const char *remain, void *opaque,
|
||||
idnode_t **(*rootfn)(void));
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
|
Loading…
Add table
Reference in a new issue