diff --git a/src/webui/extjs_dvb.c b/src/webui/extjs_dvb.c index 200465e3..eda410dd 100644 --- a/src/webui/extjs_dvb.c +++ b/src/webui/extjs_dvb.c @@ -16,6 +16,7 @@ * along with this program. If not, see . */ +#define _GNU_SOURCE #include #include #include @@ -39,13 +40,25 @@ #include "input.h" +extern const idclass_t mpegts_input_class; +extern const idclass_t mpegts_network_class; +extern const idclass_t mpegts_mux_class; +extern const idclass_t mpegts_service_class; + typedef struct extjs_grid_conf { - int start; - int limit; - htsmsg_t *filter; + int start; + int limit; + idnode_filter_t filter; + idnode_sort_t sort; } extjs_grid_conf_t; +static struct strtab extjs_filtcmp_tab[] = { + { "gt", IC_GT }, + { "lt", IC_LT }, + { "eq", IC_EQ } +}; + static void extjs_grid_conf ( struct http_arg_list *args, extjs_grid_conf_t *conf ) @@ -59,45 +72,40 @@ extjs_grid_conf conf->limit = atoi(str); else conf->limit = 50; - if ((str = http_arg_get(args, "filter"))) - conf->filter = htsmsg_json_deserialize(str); - else - conf->filter = NULL; -} - -static int -extjs_idnode_filter - ( idnode_t *in, htsmsg_t *filter ) -{ - htsmsg_t *e; - htsmsg_field_t *f; - const char *k, *t; - - HTSMSG_FOREACH(f, filter) { - if (!(e = htsmsg_get_map_by_field(f))) continue; - if (!(k = htsmsg_get_str(e, "field"))) continue; - if (!(t = htsmsg_get_str(e, "type"))) continue; - if (!strcmp(t, "string")) { - const char *str = idnode_get_str(in, k); - if (!strstr(str ?: "", htsmsg_get_str(e, "value") ?: "")) - return 0; - } else if (!strcmp(t, "numeric")) { - uint32_t u32, val; - if (!idnode_get_u32(in, k, &u32)) { - const char *op = htsmsg_get_str(e, "comparison"); - if (!op) continue; - if (htsmsg_get_u32(e, "value", &val)) continue; - if (!strcmp(op, "lt")) { - if (u32 > val) return 0; - } else if (!strcmp(op, "gt")) { - if (u32 < val) return 0; - } else { - if (u32 != val) return 0; + if ((str = http_arg_get(args, "filter"))) { + htsmsg_field_t *f; + htsmsg_t *e, *t = htsmsg_json_deserialize(str); + HTSMSG_FOREACH(f, t) { + const char *k, *t, *v; + if (!(e = htsmsg_get_map_by_field(f))) continue; + if (!(k = htsmsg_get_str(e, "field"))) continue; + if (!(t = htsmsg_get_str(e, "type"))) continue; + if (!strcmp(t, "string")) { + if ((v = htsmsg_get_str(e, "value"))) + idnode_filter_add_str(&conf->filter, k, v, IC_RE); + } else if (!strcmp(t, "numeric")) { + uint32_t v; + if (!htsmsg_get_u32(e, "value", &v)) { + int t = str2val(htsmsg_get_str(e, "comparison") ?: "", + extjs_filtcmp_tab); + idnode_filter_add_num(&conf->filter, k, v, t == -1 ? IC_EQ : t); } + } else if (!strcmp(t, "boolean")) { + uint32_t v; + if (!htsmsg_get_u32(e, "value", &v)) + idnode_filter_add_bool(&conf->filter, k, v, IC_EQ); } } + htsmsg_destroy(t); } - return 1; + if ((str = http_arg_get(args, "sort"))) { + conf->sort.key = str; + if ((str = http_arg_get(args, "dir")) && !strcmp(str, "DESC")) + conf->sort.dir = IS_DSC; + else + conf->sort.dir = IS_ASC; + } else + conf->sort.key = NULL; } // TODO: move this @@ -112,6 +120,27 @@ extjs_idnode_class ( const idclass_t *idc ) return ret; } +static void +extjs_idnode_grid + (idnode_set_t *ins, extjs_grid_conf_t *conf, htsmsg_t *out) +{ + int i; + htsmsg_t *list = htsmsg_create_list(); + if (conf->sort.key) + idnode_set_sort(ins, &conf->sort); + for (i = conf->start; i < ins->is_count && conf->limit > 0; i++, conf->limit--) { + htsmsg_t *e = htsmsg_create_map(); + htsmsg_add_str(e, "uuid", idnode_uuid_as_str(ins->is_array[i])); + idnode_save(ins->is_array[i], e); + htsmsg_add_msg(list, NULL, e); + } + pthread_mutex_unlock(&global_lock); + free(ins->is_array); + idnode_filter_clear(&conf->filter); + htsmsg_add_msg(out, "entries", list); + htsmsg_add_u32(out, "total", ins->is_count); +} + static int extjs_mpegts_service (http_connection_t *hc, const char *remain, void *opaque) @@ -123,38 +152,22 @@ extjs_mpegts_service htsbuf_queue_t *hq = &hc->hc_reply; const char *op = http_arg_get(&hc->hc_req_args, "op"); htsmsg_t *out = htsmsg_create_map(); - extjs_grid_conf_t conf; - int total = 0; + extjs_grid_conf_t conf = { 0 }; if (!strcmp(op, "list")) { - htsmsg_t *list = htsmsg_create_list(); + idnode_set_t ins = { 0 }; extjs_grid_conf(&hc->hc_req_args, &conf); pthread_mutex_lock(&global_lock); LIST_FOREACH(mn, &mpegts_network_all, mn_global_link) { LIST_FOREACH(mm, &mn->mn_muxes, mm_network_link) { LIST_FOREACH(ms, &mm->mm_services, s_dvb_mux_link) { - if (conf.filter && !extjs_idnode_filter(&ms->s_id, conf.filter)) - continue; - total++; - if (conf.start-- > 0) - continue; - if (conf.limit) { - conf.limit--; - htsmsg_t *e = htsmsg_create_map(); - htsmsg_add_str(e, "uuid", idnode_uuid_as_str(&ms->s_id)); - idnode_save(&ms->s_id, e); - htsmsg_add_msg(list, NULL, e); - conf.limit--; - } + idnode_set_add(&ins, (idnode_t*)ms, &conf.filter); } } } - pthread_mutex_unlock(&global_lock); - htsmsg_add_msg(out, "entries", list); - htsmsg_add_u32(out, "total", total); + extjs_idnode_grid(&ins, &conf, out); } else if (!strcmp(op, "class")) { - extern const idclass_t mpegts_service_class; - htsmsg_t *list= extjs_idnode_class(&mpegts_service_class); + htsmsg_t *list = extjs_idnode_class(&mpegts_service_class); htsmsg_add_msg(out, "entries", list); } @@ -170,49 +183,25 @@ static int extjs_mpegts_mux (http_connection_t *hc, const char *remain, void *opaque) { - char buf[256]; mpegts_network_t *mn; mpegts_mux_t *mm; - mpegts_service_t *ms; htsbuf_queue_t *hq = &hc->hc_reply; const char *op = http_arg_get(&hc->hc_req_args, "op"); htsmsg_t *out = htsmsg_create_map(); - extjs_grid_conf_t conf; - int s, total = 0; + extjs_grid_conf_t conf = { 0 }; if (!strcmp(op, "list")) { - htsmsg_t *list = htsmsg_create_list(); + idnode_set_t ins = { 0 }; extjs_grid_conf(&hc->hc_req_args, &conf); - pthread_mutex_lock(&global_lock); LIST_FOREACH(mn, &mpegts_network_all, mn_global_link) { LIST_FOREACH(mm, &mn->mn_muxes, mm_network_link) { - if (conf.filter && !extjs_idnode_filter(&mm->mm_id, conf.filter)) - continue; - total++; - if (conf.start-- > 0) - continue; - if (conf.limit) { - s = 0; - conf.limit--; - htsmsg_t *e = htsmsg_create_map(); - htsmsg_add_str(e, "uuid", idnode_uuid_as_str(&mm->mm_id)); - idnode_save(&mm->mm_id, e); - mn->mn_display_name(mn, buf, sizeof(buf)); - htsmsg_add_str(e, "network", buf); - LIST_FOREACH(ms, &mm->mm_services, s_dvb_mux_link) - s++; - htsmsg_add_u32(e, "num_svc", s); - htsmsg_add_msg(list, NULL, e); - } + idnode_set_add(&ins, (idnode_t*)mm, &conf.filter); } } - pthread_mutex_unlock(&global_lock); - htsmsg_add_msg(out, "entries", list); - htsmsg_add_u32(out, "total", total); + extjs_idnode_grid(&ins, &conf, out); } else if (!strcmp(op, "class")) { - extern const idclass_t mpegts_mux_class; - htsmsg_t *list= extjs_idnode_class(&mpegts_mux_class); + htsmsg_t *list = extjs_idnode_class(&mpegts_mux_class); htsmsg_add_msg(out, "entries", list); } @@ -228,48 +217,22 @@ extjs_mpegts_network (http_connection_t *hc, const char *remain, void *opaque) { mpegts_network_t *mn; - mpegts_mux_t *mm; - mpegts_service_t *ms; htsbuf_queue_t *hq = &hc->hc_reply; const char *op = http_arg_get(&hc->hc_req_args, "op"); htsmsg_t *out = htsmsg_create_map(); - extjs_grid_conf_t conf; - int s, m, total = 0; + extjs_grid_conf_t conf = { 0 }; if (!strcmp(op, "list")) { - htsmsg_t *list = htsmsg_create_list(); + idnode_set_t ins = { 0 }; extjs_grid_conf(&hc->hc_req_args, &conf); - pthread_mutex_lock(&global_lock); LIST_FOREACH(mn, &mpegts_network_all, mn_global_link) { - if (conf.filter && !extjs_idnode_filter(&mn->mn_id, conf.filter)) - continue; - total++; - if (conf.start-- > 0) - continue; - if (conf.limit) { - s = m = 0; - conf.limit--; - htsmsg_t *e = htsmsg_create_map(); - htsmsg_add_str(e, "uuid", idnode_uuid_as_str(&mn->mn_id)); - idnode_save(&mn->mn_id, e); - LIST_FOREACH(mm, &mn->mn_muxes, mm_network_link) { - m++; - LIST_FOREACH(ms, &mm->mm_services, s_dvb_mux_link) - s++; - } - htsmsg_add_u32(e, "num_mux", m); - htsmsg_add_u32(e, "num_svc", s); - htsmsg_add_msg(list, NULL, e); - } + idnode_set_add(&ins, (idnode_t*)mn, &conf.filter); } - pthread_mutex_unlock(&global_lock); - htsmsg_add_msg(out, "entries", list); - htsmsg_add_u32(out, "total", total); + extjs_idnode_grid(&ins, &conf, out); } else if (!strcmp(op, "class")) { - extern const idclass_t mpegts_network_class; - htsmsg_t *list= extjs_idnode_class(&mpegts_network_class); - htsmsg_add_msg(out, "entries", list); + htsmsg_t *c = extjs_idnode_class(&mpegts_network_class); + htsmsg_add_msg(out, "entries", c); } htsmsg_json_serialize(out, hq, 0); @@ -283,39 +246,37 @@ static int extjs_mpegts_input (http_connection_t *hc, const char *remain, void *opaque) { - extern const idclass_t mpegts_input_class; mpegts_input_t *mi; mpegts_network_t *mn; htsbuf_queue_t *hq = &hc->hc_reply; const char *op = http_arg_get(&hc->hc_req_args, "op"); htsmsg_t *out = htsmsg_create_map(); - extjs_grid_conf_t conf; - int total = 0; + extjs_grid_conf_t conf = { 0 }; if (!op) return 404; if (!strcmp(op, "list")) { + int i; + idnode_set_t ins = { 0 }; htsmsg_t *list = htsmsg_create_list(); extjs_grid_conf(&hc->hc_req_args, &conf); - pthread_mutex_lock(&global_lock); LIST_FOREACH(mi, &mpegts_input_all, mi_global_link) { - if (conf.filter && !extjs_idnode_filter(&mi->mi_id, conf.filter)) - continue; - total++; - if (conf.start-- > 0) - continue; - if (conf.limit != 0) { - if (conf.limit > 0) conf.limit--; - htsmsg_t *e = htsmsg_create_map(); - htsmsg_add_str(e, "uuid", idnode_uuid_as_str(&mi->mi_id)); - idnode_save(&mi->mi_id, e); - htsmsg_add_msg(list, NULL, e); - } + idnode_set_add(&ins, (idnode_t*)mi, &conf.filter); + } + if (conf.sort.key) + idnode_set_sort(&ins, &conf.sort); + for (i = conf.start; i < ins.is_count && conf.limit > 0; i++, conf.limit--) { + htsmsg_t *e = htsmsg_create_map(); + htsmsg_add_str(e, "uuid", idnode_uuid_as_str(ins.is_array[i])); + idnode_save(ins.is_array[i], e); + htsmsg_add_msg(list, NULL, e); } pthread_mutex_unlock(&global_lock); + free(ins.is_array); + idnode_filter_clear(&conf.filter); htsmsg_add_msg(out, "entries", list); - htsmsg_add_u32(out, "total", total); + htsmsg_add_u32(out, "total", ins.is_count); } else if (!strcmp(op, "class")) { htsmsg_t *list= extjs_idnode_class(&mpegts_input_class); htsmsg_add_msg(out, "entries", list); diff --git a/src/webui/static/app/idnode.js b/src/webui/static/app/idnode.js index 677e3d2b..3cd10b99 100644 --- a/src/webui/static/app/idnode.js +++ b/src/webui/static/app/idnode.js @@ -157,9 +157,6 @@ tvheadend.idnode_grid = function(panel, conf) var addBtn = null; var delBtn = null; - /* Load Class */ - d = json_decode(d); - /* Process */ for (i = 0; i < d.length; i++) { var type = 'string'; @@ -206,6 +203,7 @@ tvheadend.idnode_grid = function(panel, conf) id : 'uuid', totalProperty : 'total', fields : fields, + remoteSort : true, baseParams : { op : 'list', } @@ -309,11 +307,19 @@ tvheadend.idnode_grid = function(panel, conf) panel.add(grid); } - Ext.Ajax.request({ - url : conf.url, - success : build, - params : { - op: 'class' - } - }); + /* Request data */ + if (!conf.fields) { + Ext.Ajax.request({ + url : conf.url, + params : { + op: 'class' + }, + success : function(d) + { + build(json_decode(d)); + } + }); + } else { + build(conf.fields); + } } diff --git a/src/webui/static/app/mpegts.js b/src/webui/static/app/mpegts.js index ce4389a7..5ac2b1ac 100644 --- a/src/webui/static/app/mpegts.js +++ b/src/webui/static/app/mpegts.js @@ -8,14 +8,38 @@ tvheadend.networks = function(panel) { + var fields = [ + { + type : 'str', + id : 'name', + caption : 'Network Name' + }, + { + type : 'u16', + id : 'nid', + caption : 'Network ID' + }, + { + type : 'bool', + id : 'initscan', + caption : 'Initial scan' + }, + { + type : 'bool', + id : 'autodiscovery', + caption : 'Auto-discovery' + } + ]; + tvheadend.idnode_grid(panel, { - title : 'Networks', - url : 'api/mpegts/network', + title : 'Network', + url : 'api/mpegts/network', + //fields : fields, add : { url : 'api/mpegts/input', title : 'Network', select : { - label : 'Input', + caption : 'Input', params : { op: 'list', limit: -1 }, displayField : 'fe_path',//displayname', valueField : 'uuid',