ptr = ((void*)self) + p->off;
switch (p->type) {
case PT_INT:
+ case PT_BOOL:
*u32 = *(int*)ptr;
return 0;
case PT_U16:
case PT_INT:
case PT_U16:
case PT_U32:
+ case PT_BOOL:
{
uint32_t u32a = 0, u32b = 0;
idnode_get_u32(ina, sort->key, &u32a);
}
break;
case PT_DBL:
- case PT_BOOL:
// TODO
break;
}
idnode_write0 ( idnode_t *self, htsmsg_t *c, int optmask, int dosave )
{
int save = 0;
+ void (*savefn)(idnode_t*) = NULL;
const idclass_t *idc = self->in_class;
- for (; idc; idc = idc->ic_super)
+ for (; idc; idc = idc->ic_super) {
save |= prop_write_values(self, idc->ic_properties, c, optmask, NULL);
- if (save) {
- if (dosave) {
- for(; idc != NULL; idc = idc->ic_super) {
- if(idc->ic_save != NULL) {
- idc->ic_save(self);
- break;
- }
- }
- }
+ if (!savefn && idc->ic_save)
+ savefn = idc->ic_save;
+ }
+ if (save && dosave) {
+ if (savefn) savefn(self);
idnode_notify(self, NULL, 0);
}
return save;
idnode_notify
(idnode_t *in, const char *chn, int force)
{
+ const char *uuid = idnode_uuid_as_str(in);
+
/* Forced */
if (chn || force) {
- htsmsg_t *m = idnode_serialize0(in, 0);
- notify_by_msg(chn ?: "idnodeParamsChanged", m);
+ htsmsg_t *m = htsmsg_create_map();
+ htsmsg_add_str(m, "uuid", uuid);
+ notify_by_msg(chn ?: "idnodeUpdated", m);
/* Rate-limited */
} else {
pthread_mutex_lock(&idnode_mutex);
if (!idnode_queue)
idnode_queue = htsmsg_create_map();
- htsmsg_set_u32(idnode_queue, idnode_uuid_as_str(in), 1);
+ htsmsg_set_u32(idnode_queue, uuid, 1);
pthread_cond_signal(&idnode_cond);
pthread_mutex_unlock(&idnode_mutex);
}
idnode_notify(in, NULL, 0);
}
+void
+idnode_notify_title_changed (void *in)
+{
+ htsmsg_t *m = htsmsg_create_map();
+ htsmsg_add_str(m, "uuid", idnode_uuid_as_str(in));
+ htsmsg_add_str(m, "text", idnode_get_title(in));
+ notify_by_msg("idnodeUpdated", m);
+}
+
/*
* Thread for handling notifications
*/
HTSMSG_FOREACH(f, q) {
node = idnode_find(f->hmf_name, NULL);
- if (node) {
- m = idnode_serialize0(node, 0);
- if (m)
- notify_by_msg("idnodeUpdated", m);
- } else {
- m = htsmsg_create_map();
- htsmsg_add_str(m, "uuid", f->hmf_name);
+ m = htsmsg_create_map();
+ htsmsg_add_str(m, "uuid", f->hmf_name);
+ if (node)
+ notify_by_msg("idnodeUpdated", m);
+ else
notify_by_msg("idnodeDeleted", m);
- }
}
/* Finished */
pthread_mutex_unlock(&global_lock);
htsmsg_destroy(q);
+
+ /* Wait */
+ usleep(500000);
pthread_mutex_lock(&idnode_mutex);
}
}
static int
-extjs_idnode
- (http_connection_t *hc, const char *remain, void *opaque)
+extjs_idnode_tree
+ ( http_connection_t *hc, const char *uuid, const char *root,
+ idnode_set_t *(*rootfn)(void), htsmsg_t **out )
{
- htsbuf_queue_t *hq = &hc->hc_reply;
- int isroot = 0;
- htsmsg_t *out = NULL;
+ int isroot;
idnode_t *node = NULL;
- const char *uuid = http_arg_get(&hc->hc_req_args, "uuid");
- const char *op = http_arg_get(&hc->hc_req_args, "op");
-#if 0
- const char *root = http_arg_get(&hc->hc_req_args, "root");
- if (uuid == NULL)
- uuid = http_arg_get(&hc->hc_req_args, "node");
- if (!strcmp(uuid, "root")) {
- isroot = 1;
- uuid = root;
- }
- if (op == NULL)
- op = "get";
- if(uuid == NULL)
+ /* Validate */
+ if (!uuid)
+ return HTTP_STATUS_BAD_REQUEST;
+ isroot = !strcmp("root", uuid);
+ if (isroot && !(root || rootfn))
return HTTP_STATUS_BAD_REQUEST;
-#endif
pthread_mutex_lock(&global_lock);
- if(http_access_verify(hc, ACCESS_ADMIN)) {
- pthread_mutex_unlock(&global_lock);
- return HTTP_STATUS_UNAUTHORIZED;
+ if (!isroot || root) {
+ if (!(node = idnode_find(isroot ? root : uuid, NULL))) {
+ pthread_mutex_unlock(&global_lock);
+ return HTTP_STATUS_BAD_REQUEST;
+ }
}
-#if 0
- node = idnode_find(uuid, NULL);
-#endif
+ *out = htsmsg_create_list();
- if (!strcmp(op, "get")) {
- out = htsmsg_create_list();
+ /* Root node */
+ if (isroot && node) {
htsmsg_t *m = idnode_serialize(node);
htsmsg_add_u32(m, "leaf", idnode_is_leaf(node));
- htsmsg_add_msg(out, NULL, m);
+ htsmsg_add_msg(*out, NULL, m);
+
+ /* Children */
+ } else {
+ idnode_set_t *v = node ? idnode_get_childs(node) : rootfn();
+ if (v) {
+ int i;
+ for(i = 0; i < v->is_count; i++) {
+ htsmsg_t *m = idnode_serialize(v->is_array[i]);
+ htsmsg_add_u32(m, "leaf", idnode_is_leaf(v->is_array[i]));
+ htsmsg_add_msg(*out, NULL, m);
+ }
+ idnode_set_free(v);
+ }
+ }
+ pthread_mutex_unlock(&global_lock);
+
+ return 0;
+}
+
+static int
+extjs_idnode0
+ (http_connection_t *hc, const char *remain, void *opaque,
+ idnode_set_t *(*rootfn)(void))
+{
+ htsbuf_queue_t *hq = &hc->hc_reply;
+ htsmsg_t *out = NULL;
+ idnode_t *node = NULL;
+ const char *uuid, *root, *op = http_arg_get(&hc->hc_req_args, "op");
+
+ if (!op) return HTTP_STATUS_BAD_REQUEST;
+
+ /* Get details */
+ if (!strcmp(op, "get")) {
+ if (!(uuid = http_arg_get(&hc->hc_req_args, "uuid")))
+ return HTTP_STATUS_BAD_REQUEST;
+ pthread_mutex_lock(&global_lock);
+ if (!(node = idnode_find(uuid, NULL))) {
+ pthread_mutex_unlock(&global_lock);
+ return HTTP_STATUS_BAD_REQUEST;
+ }
+ out = htsmsg_create_map();
+ htsmsg_t *m = idnode_serialize(node);
+ htsmsg_add_u32(m, "leaf", idnode_is_leaf(node));
+ htsmsg_add_msg(out, "nodes", m);
+
+ /* Update */
} else if (!strcmp(op, "save")) {
const char *s;
- htsmsg_t *conf;
+ htsmsg_field_t *f;
+ htsmsg_t *conf, *nodes;
if ((s = http_arg_get(&hc->hc_req_args, "nodes"))) {
-printf("s = %s\n", s);
- htsmsg_t *nodes = htsmsg_json_deserialize(s);
- htsmsg_field_t *f;
- if (nodes) {
+ if ((nodes = htsmsg_json_deserialize(s))) {
+ pthread_mutex_lock(&global_lock);
HTSMSG_FOREACH(f, nodes) {
if (!(conf = htsmsg_get_map_by_field(f))) continue;
if (!(uuid = htsmsg_get_str(conf, "uuid"))) continue;
if (!(node = idnode_find(uuid, NULL))) continue;
idnode_update(node, conf);
}
+ pthread_mutex_unlock(&global_lock);
htsmsg_destroy(nodes);
}
- } else if ((s = http_arg_get(&hc->hc_req_args, "conf"))) {
- if ((conf = htsmsg_json_deserialize(s))) {
- idnode_update(node, conf);
- htsmsg_destroy(conf);
- }
}
out = htsmsg_create_map();
+
+ /* Children */
} else if (!strcmp(op, "childs")) {
- out = htsmsg_create_list();
- if (isroot) {
- htsmsg_t *m = idnode_serialize(node);
- htsmsg_add_u32(m, "leaf", idnode_is_leaf(node));
- htsmsg_add_msg(out, NULL, m);
- } else {
- idnode_set_t *v;
- if ((v = idnode_get_childs(node))) {
- int i;
- for(i = 0; i < v->is_count; i++) {
- htsmsg_t *m = idnode_serialize(v->is_array[i]);
- htsmsg_add_u32(m, "leaf", idnode_is_leaf(v->is_array[i]));
- htsmsg_add_msg(out, NULL, m);
- }
- idnode_set_free(v);
- }
- }
+ int e;
+ uuid = http_arg_get(&hc->hc_req_args, "uuid");
+ root = http_arg_get(&hc->hc_req_args, "root");
+ if ((e = extjs_idnode_tree(hc, uuid, root, rootfn, &out)))
+ return e;
}
- pthread_mutex_unlock(&global_lock);
-
if (!out)
return HTTP_STATUS_BAD_REQUEST;
return 0;
}
-/**
- *
- */
static int
-extjs_get_idnode(http_connection_t *hc, const char *remain, void *opaque,
- idnode_set_t *(*rootfn)(void))
+extjs_idnode
+ (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_set_t *v;
-
- if(!strcmp(s, "root")) {
- v = rootfn();
- } else {
- v = idnode_get_childs(idnode_find(s, NULL));
- }
-
- if(v != NULL) {
- int i;
- for(i = 0; i < v->is_count; i++) {
- htsmsg_t *m = idnode_serialize(v->is_array[i]);
- htsmsg_add_u32(m, "leaf", idnode_is_leaf(v->is_array[i]));
- htsmsg_add_msg(out, NULL, m);
- }
- }
-
- pthread_mutex_unlock(&global_lock);
-
- if (v) idnode_set_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_idnode0(hc, remain, opaque, NULL);
}
/**
static int
extjs_tvadapters(http_connection_t *hc, const char *remain, void *opaque)
{
- return extjs_get_idnode(hc, remain, opaque, &linuxdvb_root);
+ return extjs_idnode0(hc, remain, opaque, &linuxdvb_root);
}
/* Buttons */
var saveBtn = new Ext.Button({
- text : 'Save',
+ text : 'Save',
handler : function() {
+ var node = panel.getForm().getFieldValues();
+ node.uuid = item.uuid;
var params = {
- uuid: item.uuid,
- op : 'save',
- conf: Ext.util.JSON.encode(panel.getForm().getFieldValues())
+ op : 'save',
+ nodes : Ext.util.JSON.encode([node])
};
Ext.Ajax.request({
- url : 'api/idnode',
- params : params,
+ url : 'api/idnode',
+ params : params,
success : function(d) {
}
});
labelWidth : 200,
autoWidth : true,
autoHeight : !conf.fixedHeight,
- width : 600,
+ width : 600,
//defaults: {width: 330},
defaultType : 'textfield',
buttonAlign : 'left',
}
/* Grid Panel */
+ var auto = new Ext.form.Checkbox({
+ checked : true,
+ listeners : {
+ check : function ( s, c ) {
+ if (c) store.reload();
+ }
+ }
+ });
var grid = new Ext.grid.EditorGridPanel({
stripeRows : true,
title : conf.titleP,
pageSize : 50,
displayInfo : true,
displayMsg : conf.titleP + ' {0} - {1} of {2}',
- emptyMsg : 'No ' + conf.titleP.toLowerCase() + ' to display'
+ emptyMsg : 'No ' + conf.titleP.toLowerCase() + ' to display',
+ items : [ '-', 'Auto-refresh', auto ]
})
});
panel.add(grid);
/* Add comet listeners */
- if (conf.comet) {
- tvheadend.comet.on(conf.comet, function(o) {
- var fs = [];
- var d = {};
- for ( i = 0; i < o.params.length; i++)
- if (o.params[i].id) {
- fs.push(o.params[i].id);
- d[o.params[i].id] = o.params[i].value;
- }
- var rec = Ext.data.Record.create(fs);
- rec = new rec(d, o.id);
- store.add(rec);
- });
- }
- tvheadend.comet.on('idnodeParamsChanged', function(o) {
- var r = store.getById(o.id);
- if (r) {
- for ( i = 0; i < o.params.length; i++)
- if (o.params[i].id)
- r.set(o.params[i].id, o.params[i].value);
- r.commit();
- }
- });
+ var update = function(o) {
+ if (auto.getValue())
+ store.reload();
+ };
+ if (conf.comet)
+ tvheadend.comet.on(conf.comet, update);
+ tvheadend.comet.on('idnodeUpdated', update);
+ tvheadend.comet.on('idnodeDeleted', update);
}
/* Request data */
tvheadend.idnode_tree = function (conf)
{
var current = null;
-
+ var params = conf.params || {};
+ params.op = 'childs';
var loader = new Ext.tree.TreeLoader({
- dataUrl : conf.url,
- baseParams : conf.params,
+ dataUrl : conf.url,
+ baseParams : params,
preloadChildren : conf.preload,
+ nodeParameter : 'uuid'
});
var tree = new Ext.tree.TreePanel({
- loader : loader,
- flex : 1,
- border : false,
- root : new Ext.tree.AsyncTreeNode({
- id : conf.root || 'root',
- text : conf.title || ''
+ loader : loader,
+ flex : 1,
+ border : false,
+ root : new Ext.tree.AsyncTreeNode({
+ id : conf.root || 'root',
+ text : conf.title || ''
}),
listeners : {
click: function(n) {
}
});
- tvheadend.comet.on('idnodeNameChanged', function(o) {
- var n = tree.getNodeById(o.id);
- if(n) {
- n.setText(o.text);
+ // TODO: top-level reload
+ tvheadend.comet.on('idnodeUpdated', function(o) {
+ var n = tree.getNodeById(o.uuid);
+ if (n) {
+ if (o.text) n.setText(o.text);
+ loader.load(n);
}
});
- tvheadend.comet.on('idnodeParamsChanged', function(o) {
- var n = tree.getNodeById(o.id);
- if(n) {
- n.attributes.params = o.params;
- }
- });
-
var panel = new Ext.Panel({
- title : conf.title || '',
- layout : 'hbox',
- flex : 1,
- padding : 5,
- border : false,
+ title : conf.title || '',
+ layout : 'hbox',
+ flex : 1,
+ padding : 5,
+ border : false,
layoutConfig : {
align : 'stretch'
},