]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
api webui: migrated most of the new web API stuff to the new API subsystem
authorAdam Sutton <dev@adamsutton.me.uk>
Thu, 15 Aug 2013 11:05:04 +0000 (12:05 +0100)
committerAdam Sutton <dev@adamsutton.me.uk>
Thu, 15 Aug 2013 11:05:04 +0000 (12:05 +0100)
Makefile
src/api.c
src/api.h
src/api/api_idnode.c
src/api/api_mpegts.c [new file with mode: 0644]
src/webui/extjs.c
src/webui/extjs_dvb.c [deleted file]
src/webui/extjs_v4l.c [deleted file]
src/webui/webui_api.c

index 11674b16baea67d71b3457b63ac38b9f37d1a855..a6786585b393d913fa11d32a41a3b84e0491becf 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -112,6 +112,7 @@ SRCS =  src/version.c \
 SRCS += \
        src/api.c \
        src/api/api_idnode.c \
+       src/api/api_mpegts.c \
 
 SRCS += \
        src/parsers/parsers.c \
@@ -136,7 +137,6 @@ SRCS += src/dvr/dvr_db.c \
 SRCS += src/webui/webui.c \
        src/webui/comet.c \
        src/webui/extjs.c \
-       src/webui/extjs_dvb.c \
        src/webui/simpleui.c \
        src/webui/statedump.c \
        src/webui/html.c\
@@ -208,11 +208,6 @@ SRCS-${CONFIG_TIMESHIFT} += \
 SRCS-${CONFIG_INOTIFY} += \
        src/dvr/dvr_inotify.c \
 
-# V4L
-SRCS-${CONFIG_V4L} += \
-       src/v4l.c \
-       src/webui/extjs_v4l.c \
-
 # Avahi
 SRCS-$(CONFIG_AVAHI) += src/avahi.c
 
index 069e18d2a76f2b0caada79fd1265ef3f5223fbf2..529f6d8ff2edf5dce4e68dcbc6d229e0bbcfddc5 100644 (file)
--- a/src/api.c
+++ b/src/api.c
@@ -116,4 +116,5 @@ void api_init ( void )
 
   /* Subsystems */
   api_idnode_init();
+  api_mpegts_init();
 }
index 02463c5fae978a0b730014b7714dc344f4524368..8c69a73ae723df42f23a9f704d30f1dee7101e8b 100644 (file)
--- a/src/api.h
+++ b/src/api.h
@@ -55,14 +55,33 @@ int  api_exec ( const char *subsystem, htsmsg_t *args, htsmsg_t **resp );
 /*
  * Initialise
  */
-void api_init ( void );
+void api_init        ( void );
 void api_idnode_init ( void );
+void api_mpegts_init ( void );
 
 /*
- * Re-usable functions
+ * IDnode
  */
-int api_idnode_tree0
-  ( const char *uuid, const char *root, idnode_set_t *(*rootfn)(void),
-    htsmsg_t **resp );
+typedef struct api_idnode_grid_conf
+{
+  int             start;
+  int             limit;
+  idnode_filter_t filter;
+  idnode_sort_t   sort;
+} api_idnode_grid_conf_t;
+
+typedef void (*api_idnode_grid_callback_t)
+  (idnode_set_t*, api_idnode_grid_conf_t*);
+typedef idnode_set_t *(*api_idnode_tree_callback_t)
+  (void);
+
+int api_idnode_grid
+  ( void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp );
+
+int api_idnode_class
+  ( void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp );
+
+int api_idnode_tree
+  ( void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp );
 
 #endif /* __TVH_API_H__ */
index 80a714b450f74c1c05e25e552b3199692ea78078..9ba3eccbf41be0b282d7623cdc6abe5e5423fbac 100644 (file)
 #include "htsmsg.h"
 #include "api.h"
 
+static struct strtab filtcmptab[] = {
+  { "gt", IC_GT },
+  { "lt", IC_LT },
+  { "eq", IC_EQ }
+};
+
+static void
+api_idnode_grid_conf
+  ( htsmsg_t *args, api_idnode_grid_conf_t *conf )
+{
+  htsmsg_field_t *f;
+  htsmsg_t *filter, *e;
+  const char *str;
+
+  /* Start */
+  if ((str = htsmsg_get_str(args, "start")))
+    conf->start = atoi(str);
+  else
+    conf->start = 0;
+
+  /* Limit */
+  if ((str = htsmsg_get_str(args, "limit")))
+    conf->limit = atoi(str);
+  else
+    conf->limit = 50;
+
+  /* Filter */
+  if ((filter = htsmsg_get_list(args, "filter"))) {
+    HTSMSG_FOREACH(f, filter) {
+      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") ?: "",
+                          filtcmptab);
+          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);
+      }
+    }
+  }
+
+  /* Sort */
+  if ((str = htsmsg_get_str(args, "sort"))) {
+    conf->sort.key = str;
+    if ((str = htsmsg_get_str(args, "dir")) && !strcmp(str, "DESC"))
+      conf->sort.dir = IS_DSC;
+    else
+      conf->sort.dir = IS_ASC;
+  } else
+    conf->sort.key = NULL;
+}
+
 int
-api_idnode_tree0
-  ( const char *uuid, const char *root, 
-    idnode_set_t *(*rootfn)(void), htsmsg_t **resp )
+api_idnode_grid
+  ( void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
 {
-  int      isroot;
-  idnode_t *node = NULL;
+  int i;
+  htsmsg_t *list, *e;
+  api_idnode_grid_conf_t conf = { 0 };
+  idnode_set_t ins = { 0 };
+  api_idnode_grid_callback_t cb = opaque;
 
-  /* Validate */
-  if (!uuid)
-    return EINVAL;
-  isroot = !strcmp("root", uuid);
-  if (isroot && !(root || rootfn))
-    return EINVAL;
+  /* Grid configuration */
+  api_idnode_grid_conf(args, &conf);
 
+  /* Create list */
   pthread_mutex_lock(&global_lock);
-
-  if (!isroot || root) {
-    if (!(node = idnode_find(isroot ? root : uuid, NULL))) {
-      pthread_mutex_unlock(&global_lock);
-      return EINVAL;
-    }
+  cb(&ins, &conf);
+
+  /* Sort */
+  if (conf.sort.key)
+    idnode_set_sort(&ins, &conf.sort);
+
+  /* Paginate */
+  list  = htsmsg_create_list();
+  for (i = conf.start; i < ins.is_count && conf.limit != 0; i++) {
+    e = htsmsg_create_map();
+    htsmsg_add_str(e, "uuid", idnode_uuid_as_str(ins.is_array[i]));
+    idnode_read0(ins.is_array[i], e, 0);
+    htsmsg_add_msg(list, NULL, e);
+    if (conf.limit > 0) conf.limit--;
   }
 
-  *resp = htsmsg_create_list();
+  pthread_mutex_unlock(&global_lock);
 
-  /* Root node */
-  if (isroot && node) {
-    htsmsg_t *m = idnode_serialize(node);
-    htsmsg_add_u32(m, "leaf", idnode_is_leaf(node));
-    htsmsg_add_msg(*resp, NULL, m);
+  /* Output */
+  *resp = htsmsg_create_map();
+  htsmsg_add_msg(*resp, "entries", list);
+  htsmsg_add_u32(*resp, "total",   ins.is_count);
 
-  /* 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(*resp, NULL, m);
-      }
-      idnode_set_free(v);
-    }
-  }
-  pthread_mutex_unlock(&global_lock);
+  /* Cleanup */
+  free(ins.is_array);
+  idnode_filter_clear(&conf.filter);
 
   return 0;
 }
 
 static int
-api_idnode_class
+api_idnode_load_by_class
   ( const char *class, htsmsg_t *args, htsmsg_t **resp )
 {
-  int i, brief;
+  int i, _enum;
   const idclass_t *idc;
   idnode_set_t    *is;
   idnode_t        *in;
-  htsmsg_t        *e;
+  htsmsg_t        *l, *e;
 
   // TODO: this only works if pass as integer
-  brief = htsmsg_get_bool_or_default(args, "brief", 0);
+  _enum = htsmsg_get_bool_or_default(args, "enum", 0);
 
   pthread_mutex_lock(&global_lock);
 
@@ -97,15 +154,15 @@ api_idnode_class
     return EINVAL;
   }
 
-  *resp = htsmsg_create_list();
+  l = htsmsg_create_list();
   if ((is = idnode_find_all(idc))) {
     for (i = 0; i < is->is_count; i++) {
       in = is->is_array[i];
 
       /* Name/UUID only */
-      if (brief) {
+      if (_enum) {
         e = htsmsg_create_map();
-        htsmsg_add_str(e, "key", idnode_uuid_as_str(in));
+        htsmsg_add_str(e, "key",  idnode_uuid_as_str(in));
         htsmsg_add_str(e, "val", idnode_get_title(in));
 
       /* Full record */
@@ -113,9 +170,11 @@ api_idnode_class
         e = idnode_serialize(in);
         
       if (e)
-        htsmsg_add_msg(*resp, NULL, e);
+        htsmsg_add_msg(l, NULL, e);
     }
   }
+  *resp = htsmsg_create_map();
+  htsmsg_add_msg(*resp, "entries", l);
 
   pthread_mutex_unlock(&global_lock);
 
@@ -128,13 +187,13 @@ api_idnode_load
 {
   int err = 0;
   idnode_t *in;
-  htsmsg_t *l;
+  htsmsg_t *t, *l = NULL;
   htsmsg_field_t *f;
   const char *uuid, *class;
 
   /* Class based */
   if ((class = htsmsg_get_str(args, "class")))
-    return api_idnode_class(class, args, resp);
+    return api_idnode_load_by_class(class, args, resp);
   
   /* ID based */
   if (!(f = htsmsg_field_find(args, "uuid")))
@@ -146,19 +205,20 @@ api_idnode_load
   if (f->hmf_type == HMF_STR) {
     uuid = htsmsg_field_get_string(f);
     in   = idnode_find(uuid, NULL);
-    if (in)
-      *resp = idnode_serialize(in);
-    else
+    if (in) {
+      l     = htsmsg_create_list();
+      htsmsg_add_msg(l, NULL, idnode_serialize(in));
+    } else
       err   = ENOENT;
 
   /* Multiple */
   } else if (f->hmf_type == HMF_LIST) {
-    l     = htsmsg_get_list_by_field(f);
-    *resp = htsmsg_create_list();
-    HTSMSG_FOREACH(f, l) {
+    t = htsmsg_get_list_by_field(f);
+    l = htsmsg_create_list();
+    HTSMSG_FOREACH(f, t) {
       if (!(uuid = htsmsg_field_get_string(f))) continue;
       if (!(in   = idnode_find(uuid, NULL))) continue;
-      htsmsg_add_msg(*resp, NULL, idnode_serialize(in));
+      htsmsg_add_msg(l, NULL, idnode_serialize(in));
     }
 
   /* Invalid */
@@ -166,6 +226,11 @@ api_idnode_load
     err = EINVAL;
   }
 
+  if (l) {
+    *resp = htsmsg_create_map();
+    htsmsg_add_msg(*resp, "entries", l);
+  }
+
   pthread_mutex_unlock(&global_lock);
 
   return err;
@@ -175,25 +240,194 @@ static int
 api_idnode_save
   ( void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
 {
+  int err = EINVAL;
+  idnode_t *in;
+  htsmsg_t *conf, *l;
+  htsmsg_field_t *f;
+  const char *uuid;
+
+  if (!(f = htsmsg_field_find(args, "node")))
+    return EINVAL;
+
+  pthread_mutex_lock(&global_lock);
+
+  /* Single */
+  if (f->hmf_type == HMF_MAP) {
+    conf = htsmsg_get_map_by_field(f);
+    if (!(uuid = htsmsg_get_str(conf, "uuid")))
+      goto exit;
+    if (!(in = idnode_find(uuid, NULL)))
+      goto exit;
+    idnode_update(in, conf);
+    err = 0;
+
+  /* Multiple */
+  } else if (f->hmf_type == HMF_LIST) {
+    l     = htsmsg_get_list_by_field(f);
+    HTSMSG_FOREACH(f, l) {
+      if (!(conf = htsmsg_get_map_by_field(f)))
+        continue;
+      if (!(uuid = htsmsg_get_str(conf, "uuid")))
+        continue;
+      if (!(in = idnode_find(uuid, NULL)))
+        continue;
+      idnode_update(in, conf);
+    }
+    err = 0;
+
+  /* Invalid */
+  } else {
+    err = EINVAL;
+  }
+
+  // TODO: return updated UUIDs?
+
+exit:
+  pthread_mutex_unlock(&global_lock);
+
+  return err;
+}
+
+int
+api_idnode_tree
+  ( void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
+{
+  const char *uuid;
+  const char *root = NULL;
+  int      isroot;
+  idnode_t *node = NULL;
+  api_idnode_tree_callback_t rootfn = opaque;
+
+  /* UUID */
+  if (!(uuid = htsmsg_get_str(args, "uuid")))
+    return EINVAL;
+
+  /* Root UUID */
+  if (!rootfn)
+    root = htsmsg_get_str(args, "root");
+
+  /* Is root? */
+  isroot = (strcmp("root", uuid) == 0);
+  if (isroot && !(root || rootfn))
+    return EINVAL;
+
+  pthread_mutex_lock(&global_lock);
+
+  if (!isroot || root) {
+    if (!(node = idnode_find(isroot ? root : uuid, NULL))) {
+      pthread_mutex_unlock(&global_lock);
+      return EINVAL;
+    }
+  }
+
+  *resp = 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(*resp, 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(*resp, NULL, m);
+      }
+      idnode_set_free(v);
+    }
+  }
+  pthread_mutex_unlock(&global_lock);
+
   return 0;
 }
 
+int
+api_idnode_class
+  ( void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
+{
+  int err = EINVAL;
+  const char      *name;
+  const idclass_t *idc;
+
+  pthread_mutex_lock(&global_lock);
+
+  /* Lookup */
+  if (!opaque) {
+    if (!(name = htsmsg_get_str(args, "name")))
+      goto exit;
+    if (!(idc  = idclass_find(name)))
+      goto exit;
+  
+  } else {
+    idc = opaque;
+  }
+
+  err   = 0;
+  *resp = idclass_serialize(idc);
+
+exit:
+  pthread_mutex_unlock(&global_lock);
+
+  return err;
+}
+
 static int
-api_idnode_tree
+api_idnode_delete
   ( void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
 {
-  const char *uuid = htsmsg_get_str(args, "uuid");
-  const char *root = htsmsg_get_str(args, "root");
+  int err = 0;
+  idnode_t *in;
+  htsmsg_t *l;
+  htsmsg_field_t *f;
+  const char *uuid;
+
+  /* ID based */
+  if (!(f = htsmsg_field_find(args, "uuid")))
+    return EINVAL;
 
-  return api_idnode_tree0(uuid, root, NULL, resp);
+  pthread_mutex_lock(&global_lock);
+
+  /* Single */
+  if (f->hmf_type == HMF_STR) {
+    uuid = htsmsg_field_get_string(f);
+    in   = idnode_find(uuid, NULL);
+    if (in) {
+      idnode_delete(in);
+    } else
+      err   = ENOENT;
+
+  /* Multiple */
+  } else if (f->hmf_type == HMF_LIST) {
+    l     = htsmsg_get_list_by_field(f);
+    HTSMSG_FOREACH(f, l) {
+      if (!(uuid = htsmsg_field_get_string(f))) continue;
+      if (!(in   = idnode_find(uuid, NULL))) continue;
+      idnode_delete(in);
+    }
+  }
+
+  // TODO: should we return the UUIDs that are deleted?
+  if (!err)
+    *resp = htsmsg_create_map();
+
+  pthread_mutex_unlock(&global_lock);
+
+  return err;
 }
 
 void api_idnode_init ( void )
 {
   static api_hook_t ah[] = {
-    { "idnode/load", ACCESS_ANONYMOUS, api_idnode_load, NULL },
-    { "idnode/save", ACCESS_ADMIN,     api_idnode_save, NULL },
-    { "idnode/tree", ACCESS_ANONYMOUS, api_idnode_tree, NULL },
+    { "idnode/load",   ACCESS_ANONYMOUS, api_idnode_load,   NULL },
+    { "idnode/save",   ACCESS_ADMIN,     api_idnode_save,   NULL },
+    { "idnode/tree",   ACCESS_ANONYMOUS, api_idnode_tree,   NULL },
+    { "idnode/class",  ACCESS_ANONYMOUS, api_idnode_class,  NULL },
+    { "idnode/delete", ACCESS_ADMIN,     api_idnode_delete, NULL },
     { NULL },
   };
 
diff --git a/src/api/api_mpegts.c b/src/api/api_mpegts.c
new file mode 100644 (file)
index 0000000..a20e6ae
--- /dev/null
@@ -0,0 +1,324 @@
+/*
+ *  tvheadend - API access to MPEGTS system
+ *
+ *  Copyright (C) 2013 Adam Sutton
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "tvheadend.h"
+#include "access.h"
+#include "htsmsg.h"
+#include "api.h"
+#include "input/mpegts.h"
+#if ENABLE_LINUXDVB
+#include "input/mpegts/linuxdvb.h"
+#include "input/mpegts/linuxdvb/linuxdvb_private.h"
+#endif
+
+/*
+ * Inputs
+ */
+static int
+api_mpegts_input_network_list
+  ( void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
+{
+  int i, err = EINVAL;
+  const char *uuid;
+  mpegts_input_t *mi;
+  mpegts_network_t *mn;
+  idnode_set_t *is;
+  extern const idclass_t mpegts_input_class;
+
+  if (!(uuid = htsmsg_get_str(args, "uuid")))
+    return EINVAL;
+
+  pthread_mutex_lock(&global_lock);
+
+  mi = mpegts_input_find(uuid);
+  if (!mi)
+    goto exit;
+
+  htsmsg_t     *l  = htsmsg_create_list();
+  if ((is = mi->mi_network_list(mi))) {
+    for (i = 0; i < is->is_count; i++) {
+      char buf[256];
+      htsmsg_t *e = htsmsg_create_map();
+      mn = (mpegts_network_t*)is->is_array[i];
+      htsmsg_add_str(e, "key", idnode_uuid_as_str(is->is_array[i]));
+      mn->mn_display_name(mn, buf, sizeof(buf));
+      htsmsg_add_str(e, "val", buf);
+      htsmsg_add_msg(l, NULL, e);
+    }
+    idnode_set_free(is);
+  }
+  err   = 0;
+  *resp = htsmsg_create_map();
+  htsmsg_add_msg(*resp, "entries", l);
+
+exit:
+  pthread_mutex_unlock(&global_lock);
+
+  return err;
+}
+
+/*
+ * Networks
+ */
+static void
+api_mpegts_network_grid
+  ( idnode_set_t *ins, api_idnode_grid_conf_t *conf )
+{
+  mpegts_network_t *mn;
+
+  LIST_FOREACH(mn, &mpegts_network_all, mn_global_link) {
+    idnode_set_add(ins, (idnode_t*)mn, &conf->filter);
+  }
+}
+
+static int
+api_mpegts_network_builders
+  ( void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
+{
+  mpegts_network_builder_t *mnb;
+  htsmsg_t *l, *e;
+
+  /* List of available builder classes */
+  l = htsmsg_create_list();
+  LIST_FOREACH(mnb, &mpegts_network_builders, link)
+    if ((e = idclass_serialize(mnb->idc)))
+      htsmsg_add_msg(l, NULL, e);
+
+  /* Output */
+  *resp = htsmsg_create_map();  
+  htsmsg_add_msg(*resp, "entries", l);
+
+  return 0;
+}
+
+static int
+api_mpegts_network_create
+  ( void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
+{
+  int err;
+  const char *class;
+  htsmsg_t *conf;
+  mpegts_network_t *mn;
+
+  if (!(class = htsmsg_get_str(args, "class")))
+    return -EINVAL;
+  if (!(conf  = htsmsg_get_map(args, "conf")))
+    return -EINVAL;
+
+  pthread_mutex_lock(&global_lock);
+  mn = mpegts_network_build(class, conf);
+  if (mn) {
+    err = 0;
+    *resp = htsmsg_create_map();
+    mn->mn_config_save(mn);
+  } else {
+    err = -EINVAL;
+  }
+  pthread_mutex_unlock(&global_lock);
+
+  return err;
+}
+
+static int
+api_mpegts_network_muxclass
+  ( void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
+{
+  int err = EINVAL;
+  const idclass_t *idc; 
+  mpegts_network_t *mn;
+  const char *uuid;
+
+  if (!(uuid = htsmsg_get_str(args, "uuid")))
+    return EINVAL;
+  
+  pthread_mutex_lock(&global_lock);
+  
+  if (!(mn  = mpegts_network_find(uuid)))
+    goto exit;
+
+  if (!(idc = mn->mn_mux_class(mn)))
+    goto exit;
+
+  *resp = idclass_serialize(idc);
+  err    = 0;
+
+exit:
+  pthread_mutex_unlock(&global_lock);
+  return err;
+}
+
+static int
+api_mpegts_network_muxcreate
+  ( void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
+{
+  int err = EINVAL;
+  mpegts_network_t *mn;
+  mpegts_mux_t *mm;
+  htsmsg_t *conf;
+  const char *uuid;
+
+  if (!(uuid = htsmsg_get_str(args, "uuid")))
+    return EINVAL;
+  if (!(conf = htsmsg_get_map(args, "conf")))
+    return EINVAL;
+  
+  pthread_mutex_lock(&global_lock);
+  
+  if (!(mn  = mpegts_network_find(uuid)))
+    goto exit;
+  
+  if (!(mm = mn->mn_mux_create2(mn, conf)))
+    goto exit;
+
+  mm->mm_config_save(mm);
+  err = 0;
+
+exit:
+  pthread_mutex_unlock(&global_lock);
+  return err;
+}
+
+/*
+ * Muxes
+ */
+static void
+api_mpegts_mux_grid
+  ( idnode_set_t *ins, api_idnode_grid_conf_t *conf )
+{
+  mpegts_network_t *mn;
+  mpegts_mux_t *mm;
+
+  LIST_FOREACH(mn, &mpegts_network_all, mn_global_link) {
+    LIST_FOREACH(mm, &mn->mn_muxes, mm_network_link) {
+      idnode_set_add(ins, (idnode_t*)mm, &conf->filter);
+    }
+  }
+}
+
+/*
+ * Services
+ */
+static void
+api_mpegts_service_grid
+  ( idnode_set_t *ins, api_idnode_grid_conf_t *conf )
+{
+  mpegts_network_t *mn;
+  mpegts_mux_t *mm;
+  mpegts_service_t *ms;
+
+  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) {
+        idnode_set_add(ins, (idnode_t*)ms, &conf->filter);
+      }
+    }
+  }
+}
+
+/*
+ * Satconfs
+ */
+#if ENABLE_LINUXDVB
+static void
+api_linuxdvb_satconf_grid
+  ( idnode_set_t *ins, api_idnode_grid_conf_t *conf )
+{
+  mpegts_input_t *mi;
+  extern const idclass_t linuxdvb_satconf_class;
+
+  LIST_FOREACH(mi, &mpegts_input_all, mi_global_link)
+    if (idnode_is_instance((idnode_t*)mi, &linuxdvb_satconf_class))
+      idnode_set_add(ins, (idnode_t*)mi, &conf->filter);
+}
+
+static int
+api_linuxdvb_satconf_create
+  ( void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
+{
+  int err;
+  htsmsg_t *conf;
+  idnode_t *in;
+
+  if (!(conf  = htsmsg_get_map(args, "conf")))
+    return -EINVAL;
+
+  pthread_mutex_lock(&global_lock);
+  in = (idnode_t*)linuxdvb_satconf_create0(NULL, conf);
+  if (in) {
+    err = 0;
+    in->in_class->ic_save(in);
+    *resp = htsmsg_create_map();
+  } else {
+    err = -EINVAL;
+  }
+  pthread_mutex_unlock(&global_lock);
+
+  return err;
+}
+#endif
+
+/*
+ * Adapter list
+ *
+ * TODO: this will need reworking for mpegps etc...
+ */
+static idnode_set_t *
+api_tvadapter_tree ( void )
+{
+#if ENABLE_LINUXDVB
+  return linuxdvb_root();
+#else
+  return NULL;
+#endif
+}
+
+/*
+ * Init
+ */
+void
+api_mpegts_init ( void )
+{
+  extern const idclass_t mpegts_network_class;
+  extern const idclass_t mpegts_mux_class;
+  extern const idclass_t mpegts_service_class;
+  extern const idclass_t linuxdvb_satconf_class;
+
+  static api_hook_t ah[] = {
+    { "tvadapter/tree",            ACCESS_ANONYMOUS, api_idnode_tree,  api_tvadapter_tree },
+    { "mpegts/input/network_list", ACCESS_ANONYMOUS, api_mpegts_input_network_list, NULL },
+    { "mpegts/network/grid",       ACCESS_ANONYMOUS, api_idnode_grid,  api_mpegts_network_grid },
+    { "mpegts/network/class",      ACCESS_ANONYMOUS, api_idnode_class, (void*)&mpegts_network_class },
+    { "mpegts/network/builders",   ACCESS_ANONYMOUS, api_mpegts_network_builders, NULL },
+    { "mpegts/network/create",     ACCESS_ANONYMOUS, api_mpegts_network_create,   NULL },
+    { "mpegts/network/mux_class",  ACCESS_ANONYMOUS, api_mpegts_network_muxclass, NULL },
+    { "mpegts/network/mux_create", ACCESS_ANONYMOUS, api_mpegts_network_muxcreate, NULL },
+    { "mpegts/mux/grid",           ACCESS_ANONYMOUS, api_idnode_grid,  api_mpegts_mux_grid },
+    { "mpegts/mux/class",          ACCESS_ANONYMOUS, api_idnode_class, (void*)&mpegts_mux_class },
+    { "mpegts/service/grid",       ACCESS_ANONYMOUS, api_idnode_grid,  api_mpegts_service_grid },
+    { "mpegts/service/class",      ACCESS_ANONYMOUS, api_idnode_class, (void*)&mpegts_service_class },
+#if ENABLE_LINUXDVB
+    { "linuxdvb/satconf/grid",     ACCESS_ANONYMOUS, api_idnode_grid,  api_linuxdvb_satconf_grid },
+    { "linuxdvb/satconf/class",    ACCESS_ANONYMOUS, api_idnode_class, (void*)&linuxdvb_satconf_class },
+    { "linuxdvb/satconf/create",   ACCESS_ANONYMOUS, api_linuxdvb_satconf_create, NULL },
+#endif
+    { NULL },
+  };
+
+  api_register_all(ah);
+}
index aeca6f249f1ef6a4f101faa17a7a0125db2f0191..d014dff05adec79e719d3ef2810efc7d8adcb4e7 100644 (file)
@@ -1885,161 +1885,6 @@ extjs_tvhlog(http_connection_t *hc, const char *remain, void *opaque)
   return 0;
 }
 
-static int
-extjs_idnode_tree
-  ( http_connection_t *hc, const char *uuid, const char *root,
-    idnode_set_t *(*rootfn)(void), htsmsg_t **out )
-{
-  int isroot;
-  idnode_t *node = NULL;
-
-  /* Validate */
-  if (!uuid)
-    return HTTP_STATUS_BAD_REQUEST;
-  isroot = !strcmp("root", uuid);
-  if (isroot && !(root || rootfn))
-    return HTTP_STATUS_BAD_REQUEST;
-
-  pthread_mutex_lock(&global_lock);
-
-  if (!isroot || root) {
-    if (!(node = idnode_find(isroot ? root : uuid, NULL))) {
-      pthread_mutex_unlock(&global_lock);
-      return HTTP_STATUS_BAD_REQUEST;
-    }
-  }
-
-  *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);
-
-  /* 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);
-    pthread_mutex_unlock(&global_lock);
-    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_field_t *f;
-    htsmsg_t *conf, *nodes;
-    if ((s = http_arg_get(&hc->hc_req_args, "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);
-      }
-    }
-    out = htsmsg_create_map();
-  
-  /* List by class */
-  } else if (!strcmp(op, "list")) {
-    int i;
-    const char      *cls = http_arg_get(&hc->hc_req_args, "class");
-    pthread_mutex_lock(&global_lock);
-    const idclass_t *idc = idclass_find(cls);
-    idnode_set_t    *is  = idnode_find_all(idc);
-    out = htsmsg_create_map();
-    if (is) {
-      htsmsg_t *l = htsmsg_create_list();
-      for (i = 0; i < is->is_count; i++) {
-        idnode_t *in = is->is_array[i];
-        htsmsg_t *e = htsmsg_create_map();
-        htsmsg_add_str(e, "key", idnode_uuid_as_str(in));
-        htsmsg_add_str(e, "val", idnode_get_title(in));
-        htsmsg_add_msg(l, NULL, e);
-      }
-      idnode_set_free(is);
-      htsmsg_add_msg(out, "entries", l);
-    }
-    pthread_mutex_unlock(&global_lock);
-
-  /* Children */
-  } else if (!strcmp(op, "childs")) {
-    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;
-  }
-
-  if (!out)
-    return HTTP_STATUS_BAD_REQUEST;
-
-  htsmsg_json_serialize(out, hq, 0);
-  htsmsg_destroy(out);
-  http_output_content(hc, "text/x-json; charset=UTF-8");
-  return 0;
-}
-
-static int
-extjs_idnode
-  (http_connection_t *hc, const char *remain, void *opaque)
-{
-  return extjs_idnode0(hc, remain, opaque, NULL);
-}
-
-/**
- *
- */
-static int
-extjs_tvadapters(http_connection_t *hc, const char *remain, void *opaque)
-{
-  return extjs_idnode0(hc, remain, opaque, &linuxdvb_root);
-}
-
-
-
 /**
  * Capability check
  */
@@ -2221,13 +2066,8 @@ extjs_start(void)
 #endif
   http_path_add("/tvhlog",           NULL, extjs_tvhlog,           ACCESS_ADMIN);
 
-  http_path_add("/tvadapters",
-               NULL, extjs_tvadapters, ACCESS_ADMIN);
-  http_path_add("/api/idnode2", NULL, extjs_idnode, ACCESS_ADMIN); // TODO: might want diff access for read/write`
   http_path_add("/api/service_mapping", NULL, extjs_service_mapping, ACCESS_ADMIN);
 
-  extjs_start_dvb();
-
 #if ENABLE_V4L
   extjs_start_v4l();
 #endif
diff --git a/src/webui/extjs_dvb.c b/src/webui/extjs_dvb.c
deleted file mode 100644 (file)
index d1a1cc5..0000000
+++ /dev/null
@@ -1,517 +0,0 @@
-/*
- *  tvheadend, EXTJS based interface
- *  Copyright (C) 2008 Andreas Ă–man
- *
- *  This program is free software: you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation, either version 3 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#define _GNU_SOURCE
-#include <pthread.h>
-#include <assert.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdarg.h>
-
-#include <arpa/inet.h>
-
-#include "htsmsg.h"
-#include "htsmsg_json.h"
-
-#include "tvheadend.h"
-#include "http.h"
-#include "webui.h"
-#include "access.h"
-#include "dtable.h"
-#include "channels.h"
-
-#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;
-  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 )
-{
-  const char *str;
-  if ((str = http_arg_get(args, "start")))
-    conf->start = atoi(str);
-  else
-    conf->start = 0;
-  if ((str = http_arg_get(args, "limit")))
-    conf->limit = atoi(str);
-  else
-    conf->limit = 50;
-  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);
-  }
-  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;
-}
-
-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++) {
-    htsmsg_t *e = htsmsg_create_map();
-    htsmsg_add_str(e, "uuid", idnode_uuid_as_str(ins->is_array[i]));
-    idnode_read0(ins->is_array[i], e, 0);
-    htsmsg_add_msg(list, NULL, e);
-    if (conf->limit > 0) conf->limit--;
-  }
-  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)
-{
-  //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 = { 0 };
-
-  if (!strcmp(op, "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) {
-          idnode_set_add(&ins, (idnode_t*)ms, &conf.filter);
-        }
-      }
-    }
-    extjs_idnode_grid(&ins, &conf, out);
-  } else if (!strcmp(op, "class")) {
-    htsmsg_t *list = idclass_serialize(&mpegts_service_class);
-    htsmsg_add_msg(out, "entries", list);
-  }
-
-  htsmsg_json_serialize(out, hq, 0);
-  http_output_content(hc, "text/x-json; charset=UTF-8");
-  htsmsg_destroy(out);
-
-  return 0;
-}
-
-static void
-http_api_boilerplate
-  (http_connection_t *hc, const char **op, htsmsg_t **args)
-{
-  const char *s;
-  *op = http_arg_get(&hc->hc_req_args, "op");
-  s   = http_arg_get(&hc->hc_req_args, "args");
-  if (s)
-    *args = htsmsg_json_deserialize(s);
-  else
-    *args = NULL;
-  if (!*op && *args)
-    *op   = htsmsg_get_str(*args, "method"); // HTSP compat
-}
-
-static int
-extjs_mpegts_mux
-  (http_connection_t *hc, const char *remain, void *opaque)
-{
-  mpegts_network_t *mn;
-  mpegts_mux_t     *mm;
-  htsbuf_queue_t   *hq  = &hc->hc_reply;
-  const char       *op;
-  htsmsg_t         *args;
-  htsmsg_t         *out = htsmsg_create_map();
-  extjs_grid_conf_t conf = { 0 };
-
-  http_api_boilerplate(hc, &op, &args);
-  if (!op)
-    return HTTP_STATUS_BAD_REQUEST;
-
-  if (!strcmp(op, "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) {
-        idnode_set_add(&ins, (idnode_t*)mm, &conf.filter);
-      }
-    }
-    extjs_idnode_grid(&ins, &conf, out);
-  } else if (!strcmp(op, "class")) {
-    htsmsg_t *list = idclass_serialize(&mpegts_mux_class);
-    htsmsg_add_msg(out, "entries", list);
-  } else if (!strcmp(op, "delete") && args) {
-    htsmsg_field_t *f;
-    htsmsg_t *uuids = htsmsg_get_list(args, "uuids");
-    if (uuids) {
-      pthread_mutex_lock(&global_lock);
-      HTSMSG_FOREACH(f, uuids) {
-        if (f->hmf_type == HMF_STR)
-          mpegts_mux_delete_by_uuid(f->hmf_str);
-      }
-      pthread_mutex_unlock(&global_lock);
-    }
-  }
-
-  htsmsg_json_serialize(out, hq, 0);
-  http_output_content(hc, "text/x-json; charset=UTF-8");
-  htsmsg_destroy(out);
-
-  return 0;
-}
-
-static int
-extjs_linuxdvb_satconf
-  (http_connection_t *hc, const char *remain, void *opaque)
-{
-  struct linuxdvb_satconf;
-  extern const idclass_t linuxdvb_satconf_class;
-  extern struct linuxdvb_satconf *linuxdvb_satconf_create0(const char*, htsmsg_t*);
-  mpegts_input_t   *mi;
-  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 = { 0 };
-
-  if (!strcmp(op, "list")) {
-    idnode_set_t ins = { 0 };
-    extjs_grid_conf(&hc->hc_req_args, &conf);
-    pthread_mutex_lock(&global_lock);
-    
-    LIST_FOREACH(mi, &mpegts_input_all, mi_global_link)
-      if (idnode_is_instance((idnode_t*)mi, &linuxdvb_satconf_class))
-        idnode_set_add(&ins, (idnode_t*)mi, &conf.filter);
-    extjs_idnode_grid(&ins, &conf, out);
-  } else if (!strcmp(op, "class")) {
-    htsmsg_t *list = idclass_serialize(&linuxdvb_satconf_class);
-    htsmsg_add_msg(out, "entries", list);
-  } else if (!strcmp(op, "create")) {
-    idnode_t *in;
-    htsmsg_t *conf = NULL;
-    const char *c;
-    if ((c = http_arg_get(&hc->hc_req_args, "conf")))
-      conf = htsmsg_json_deserialize(c);
-    if (!conf)
-      return HTTP_STATUS_BAD_REQUEST;
-    pthread_mutex_lock(&global_lock);
-    in = (idnode_t*)linuxdvb_satconf_create0(NULL, conf);
-    if (in) in->in_class->ic_save(in);
-    pthread_mutex_unlock(&global_lock);
-  }
-
-  htsmsg_json_serialize(out, hq, 0);
-  http_output_content(hc, "text/x-json; charset=UTF-8");
-  htsmsg_destroy(out);
-
-  return 0;
-}
-
-
-static int
-extjs_mpegts_network
-  (http_connection_t *hc, const char *remain, void *opaque)
-{
-  mpegts_network_t *mn  = NULL;
-  htsbuf_queue_t   *hq  = &hc->hc_reply;
-  const char       *op;
-  htsmsg_t         *args;
-  htsmsg_t         *out = htsmsg_create_map();
-  extjs_grid_conf_t conf = { 0 };
-
-  http_api_boilerplate(hc, &op, &args);
-  if (!op)
-    return HTTP_STATUS_BAD_REQUEST;
-
-  if (!strcmp(op, "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) {
-      idnode_set_add(&ins, (idnode_t*)mn, &conf.filter);
-    }
-    extjs_idnode_grid(&ins, &conf, out);
-  } else if (!strcmp(op, "class")) {
-    htsmsg_t *c = idclass_serialize(&mpegts_network_class);
-    htsmsg_add_msg(out, "entries", c);
-  } else if (!strcmp(op, "class_list")) {
-    mpegts_network_builder_t *mnb;
-    htsmsg_t *e, *c = htsmsg_create_list();
-    LIST_FOREACH(mnb, &mpegts_network_builders, link)
-      if ((e = idclass_serialize(mnb->idc)))
-        htsmsg_add_msg(c, NULL, e);
-    htsmsg_add_msg(out, "entries", c);
-  } else if (!strcmp(op, "delete") && args) {
-    htsmsg_field_t *f;
-    htsmsg_t *uuids = htsmsg_get_list(args, "uuids");
-    if (uuids) {
-      pthread_mutex_lock(&global_lock);
-      HTSMSG_FOREACH(f, uuids) {
-        if (f->hmf_type == HMF_STR)
-          mpegts_network_delete_by_uuid(f->hmf_str);
-      }
-      pthread_mutex_unlock(&global_lock);
-    }
-  } else if (!strcmp(op, "create")) {
-    htsmsg_t *conf = NULL;
-    const char *s, *c;
-    if (!(s = http_arg_get(&hc->hc_req_args, "conf")))
-      return HTTP_STATUS_BAD_REQUEST;
-    if (!(c = http_arg_get(&hc->hc_req_args, "class")))
-      return HTTP_STATUS_BAD_REQUEST;
-    if (!(conf = htsmsg_json_deserialize(s)))
-      return HTTP_STATUS_BAD_REQUEST;
-    pthread_mutex_lock(&global_lock);
-    mn = mpegts_network_build(c, conf);
-    if (mn) mn->mn_config_save(mn);
-    pthread_mutex_unlock(&global_lock);
-  } else if (!strcmp(op, "mux_class")) {
-    const idclass_t *idc; 
-    const char *uuid = http_arg_get(&hc->hc_req_args, "uuid");
-    pthread_mutex_lock(&global_lock);
-    mn = (uuid ? mpegts_network_find(uuid) : NULL);
-    if (!mn) {
-      pthread_mutex_unlock(&global_lock);
-      return HTTP_STATUS_BAD_REQUEST;
-    }
-    if (!(idc = mn->mn_mux_class(mn))) {
-      pthread_mutex_unlock(&global_lock);
-      return HTTP_STATUS_BAD_REQUEST;
-    }
-    htsmsg_t *c = idclass_serialize(idc);
-    htsmsg_add_msg(out, "entries", c);
-    pthread_mutex_unlock(&global_lock);
-  } else if (!strcmp(op, "mux_create")) {
-    mpegts_mux_t *mm;
-    htsmsg_t *conf = NULL;
-    const char *c;
-    const char *uuid = http_arg_get(&hc->hc_req_args, "uuid");
-    pthread_mutex_lock(&global_lock);
-    mn = (uuid ? mpegts_network_find(uuid) : NULL);
-    if (!mn) {
-      pthread_mutex_unlock(&global_lock);
-      return HTTP_STATUS_BAD_REQUEST;
-    }
-    if ((c = http_arg_get(&hc->hc_req_args, "conf")))
-      conf = htsmsg_json_deserialize(c);
-    if (!conf) {
-      pthread_mutex_unlock(&global_lock);
-      return HTTP_STATUS_BAD_REQUEST;
-    }
-    mm = mn->mn_mux_create2(mn, conf);
-    if(mm) mm->mm_config_save(mm);
-    pthread_mutex_unlock(&global_lock);
-    if (!mm) return HTTP_STATUS_BAD_REQUEST; // TODO: error message
-  } else {
-    return HTTP_STATUS_BAD_REQUEST;
-  }
-
-  htsmsg_json_serialize(out, hq, 0);
-  http_output_content(hc, "text/x-json; charset=UTF-8");
-  htsmsg_destroy(out);
-
-  return 0;
-}
-
-static int
-extjs_mpegts_input
-  (http_connection_t *hc, const char *remain, void *opaque)
-{
-  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 = { 0 };
-
-  if (!op) return 404;
-
-  if (!strcmp(op, "list")) {
-    idnode_set_t ins = { 0 };
-    extjs_grid_conf(&hc->hc_req_args, &conf);
-    pthread_mutex_lock(&global_lock);
-    LIST_FOREACH(mi, &mpegts_input_all, mi_global_link)
-      idnode_set_add(&ins, (idnode_t*)mi, &conf.filter);
-    extjs_idnode_grid(&ins, &conf, out);
-  } else if (!strcmp(op, "class")) {
-    htsmsg_t *list = idclass_serialize(&mpegts_input_class);
-    htsmsg_add_msg(out, "entries", list);
-  } else if (!strcmp(op, "network_list")) {
-    const char *uuid = http_arg_get(&hc->hc_req_args, "uuid");
-    if (!uuid) return HTTP_STATUS_BAD_REQUEST;
-    pthread_mutex_lock(&global_lock);
-    mi = mpegts_input_find(uuid);
-    if (mi) {
-      int i;
-      idnode_set_t *is = mi->mi_network_list(mi);
-      if (is) {
-        htsmsg_t     *l  = htsmsg_create_list();
-        for (i = 0; i < is->is_count; i++) {
-          char buf[256];
-          htsmsg_t *e = htsmsg_create_map();
-          mn = (mpegts_network_t*)is->is_array[i];
-          htsmsg_add_str(e, "key", idnode_uuid_as_str(is->is_array[i]));
-          mn->mn_display_name(mn, buf, sizeof(buf));
-          htsmsg_add_str(e, "val", buf);
-          htsmsg_add_msg(l, NULL, e);
-        }
-        htsmsg_add_msg(out, "entries", l);
-        idnode_set_free(is);
-      }
-    }
-    pthread_mutex_unlock(&global_lock);
-#if 0
-  } else if (!strcmp(op, "network_class")) {
-    const char *uuid = http_arg_get(&hc->hc_req_args, "uuid");
-    if (!uuid) return 404;
-    pthread_mutex_lock(&global_lock);
-    mpegts_input_t *mi = idnode_find(uuid, &mpegts_input_class);
-    if (!mi) {
-      pthread_mutex_unlock(&global_lock);
-      return 404;
-    }
-    htsmsg_t *list= idclass_serialize(mi->mi_network_class(mi));
-    htsmsg_add_msg(out, "entries", list);
-    pthread_mutex_unlock(&global_lock);
-  } else if (!strcmp(op, "network_create")) {
-    const char *uuid = http_arg_get(&hc->hc_req_args, "uuid");
-    const char *conf = http_arg_get(&hc->hc_req_args, "conf");
-    if (!uuid || !conf) return 404;
-    pthread_mutex_lock(&global_lock);
-    mi = idnode_find(uuid, &mpegts_input_class);
-    if (!mi) {
-      pthread_mutex_unlock(&global_lock);
-      return 404;
-    }
-    mn = mi->mi_network_create(mi, htsmsg_json_deserialize(conf));
-    if (mn)
-      mn->mn_config_save(mn);
-    else {
-      // TODO: Check for error
-    }
-    pthread_mutex_unlock(&global_lock);
-#endif
-  }
-
-  htsmsg_json_serialize(out, hq, 0);
-  http_output_content(hc, "text/x-json; charset=UTF-8");
-  htsmsg_destroy(out);
-
-  return 0;
-}
-
-/**
- * DVB WEB user interface
- */
-void
-extjs_start_dvb(void)
-{
-  http_path_add("/api/mpegts/network", 
-               NULL, extjs_mpegts_network, ACCESS_WEB_INTERFACE);
-  http_path_add("/api/mpegts/mux", 
-               NULL, extjs_mpegts_mux, ACCESS_WEB_INTERFACE);
-  http_path_add("/api/mpegts/service", 
-               NULL, extjs_mpegts_service, ACCESS_WEB_INTERFACE);
-  http_path_add("/api/mpegts/input", 
-               NULL, extjs_mpegts_input, ACCESS_WEB_INTERFACE);
-  http_path_add("/api/linuxdvb/satconf", 
-               NULL, extjs_linuxdvb_satconf, ACCESS_WEB_INTERFACE);
-#if 0
-  http_path_add("/dvb/locations", 
-               NULL, extjs_dvblocations, ACCESS_WEB_INTERFACE);
-
-  http_path_add("/dvb/adapter", 
-               NULL, extjs_dvbadapter, ACCESS_ADMIN);
-
-
-  http_path_add("/dvb/muxes", 
-               NULL, extjs_dvbmuxes, ACCESS_ADMIN);
-
-  http_path_add("/dvb/services", 
-               NULL, extjs_dvbservices, ACCESS_ADMIN);
-
-  http_path_add("/dvb/lnbtypes", 
-               NULL, extjs_lnbtypes, ACCESS_ADMIN);
-
-  http_path_add("/dvb/satconf", 
-               NULL, extjs_dvbsatconf, ACCESS_ADMIN);
-
-  http_path_add("/dvb/feopts", 
-               NULL, extjs_dvb_feopts, ACCESS_ADMIN);
-
-  http_path_add("/dvb/addmux", 
-               NULL, extjs_dvb_addmux, ACCESS_ADMIN);
-  http_path_add("/dvb/copymux", 
-               NULL, extjs_dvb_copymux, ACCESS_ADMIN);
-#endif
-
-}
diff --git a/src/webui/extjs_v4l.c b/src/webui/extjs_v4l.c
deleted file mode 100644 (file)
index 1055612..0000000
+++ /dev/null
@@ -1,295 +0,0 @@
-/*
- *  tvheadend, EXTJS based interface
- *  Copyright (C) 2008 Andreas Ă–man
- *
- *  This program is free software: you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation, either version 3 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <pthread.h>
-#include <assert.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdarg.h>
-
-#include <arpa/inet.h>
-
-#include "htsmsg.h"
-#include "htsmsg_json.h"
-
-#include "tvheadend.h"
-#include "http.h"
-#include "webui.h"
-#include "access.h"
-#include "channels.h"
-#include "psi.h"
-
-#include "v4l.h"
-#include "serviceprobe.h"
-
-
-
-/**
- *
- */
-static htsmsg_t *
-json_single_record(htsmsg_t *rec, const char *root)
-{
-  htsmsg_t *out, *array;
-  
-  out = htsmsg_create_map();
-  array = htsmsg_create_list();
-
-  htsmsg_add_msg(array, NULL, rec);
-  htsmsg_add_msg(out, root, array);
-  return out;
-}
-
-
-
-/**
- *
- */
-static int
-extjs_v4ladapter(http_connection_t *hc, const char *remain, void *opaque)
-{
-  htsbuf_queue_t *hq = &hc->hc_reply;
-  v4l_adapter_t *va;
-  htsmsg_t *out, *array, *r;
-  const char *op = http_arg_get(&hc->hc_req_args, "op");
-  const char *s;
-
-  pthread_mutex_lock(&global_lock);
-
-  if(remain == NULL) {
-    /* Just list all adapters */
-
-    array = htsmsg_create_list();
-
-    TAILQ_FOREACH(va, &v4l_adapters, va_global_link) 
-      htsmsg_add_msg(array, NULL, v4l_adapter_build_msg(va));
-
-    pthread_mutex_unlock(&global_lock);
-    out = htsmsg_create_map();
-    htsmsg_add_msg(out, "entries", array);
-
-    htsmsg_json_serialize(out, hq, 0);
-    htsmsg_destroy(out);
-    http_output_content(hc, "text/x-json; charset=UTF-8");
-    return 0;
-  }
-
-  if((va = v4l_adapter_find_by_identifier(remain)) == NULL) {
-    pthread_mutex_unlock(&global_lock);
-    return 404;
-  }
-
-  if(!strcmp(op, "load")) {
-    r = htsmsg_create_map();
-    htsmsg_add_str(r, "id", va->va_identifier);
-    htsmsg_add_str(r, "device", va->va_path ?: "No hardware attached");
-    htsmsg_add_str(r, "name", va->va_displayname);
-    htsmsg_add_u32(r, "logging", va->va_logging);
-    out = json_single_record(r, "v4ladapters");
-  } else if(!strcmp(op, "save")) {
-
-    if((s = http_arg_get(&hc->hc_req_args, "name")) != NULL)
-      v4l_adapter_set_displayname(va, s);
-
-    s = http_arg_get(&hc->hc_req_args, "logging");
-    v4l_adapter_set_logging(va, !!s);
-
-    out = htsmsg_create_map();
-    htsmsg_add_u32(out, "success", 1);
-
-  } else {
-    pthread_mutex_unlock(&global_lock);
-    return HTTP_STATUS_BAD_REQUEST;
-  }
-  pthread_mutex_unlock(&global_lock);
-
-  htsmsg_json_serialize(out, hq, 0);
-  htsmsg_destroy(out);
-
-  http_output_content(hc, "text/x-json; charset=UTF-8");
-  return 0;  
-}
-
-/**
- *
- */
-static void
-service_update_v4l(htsmsg_t *in)
-{
-  htsmsg_field_t *f;
-  htsmsg_t *c;
-  service_t *t;
-  uint32_t u32;
-  const char *id;
-  int save;
-
-  TAILQ_FOREACH(f, &in->hm_fields, hmf_link) {
-    if((c = htsmsg_get_map_by_field(f)) == NULL ||
-       (id = htsmsg_get_str(c, "id")) == NULL)
-      continue;
-    
-    if((t = service_find_by_identifier(id)) == NULL)
-      continue;
-
-    save = 0;
-
-    if(!htsmsg_get_u32(c, "frequency", &u32)) {
-      t->s_v4l_frequency = u32;
-      save = 1;
-    }
-    if(save)
-      t->s_config_save(t); // Save config
-  }
-}
-
-
-
-/**
- *
- */
-static htsmsg_t *
-build_record_v4l(service_t *t)
-{
-  htsmsg_t *r = htsmsg_create_map();
-
-  //  htsmsg_add_str(r, "id", t->s_identifier); // XXX(dvbreorg)
-
-  htsmsg_add_str(r, "channelname", t->s_ch ? t->s_ch->ch_name : "");
-  htsmsg_add_u32(r, "frequency", t->s_v4l_frequency);
-  htsmsg_add_u32(r, "enabled", t->s_enabled);
-  return r;
-}
-
-/**
- *
- */
-static int
-v4l_servicecmp(const void *A, const void *B)
-{
-  service_t *a = *(service_t **)A;
-  service_t *b = *(service_t **)B;
-
-  return (int)a->s_v4l_frequency - (int)b->s_v4l_frequency;
-}
-
-/**
- *
- */
-static int
-extjs_v4lservices(http_connection_t *hc, const char *remain, void *opaque)
-{
-  v4l_adapter_t *va;
-  htsbuf_queue_t *hq = &hc->hc_reply;
-  htsmsg_t *out, *in, *array;
-  const char *op        = http_arg_get(&hc->hc_req_args, "op");
-  const char *entries   = http_arg_get(&hc->hc_req_args, "entries");
-  service_t *t, **tvec;
-  int count = 0, i = 0;
-
-  pthread_mutex_lock(&global_lock);
-
-  if((va = v4l_adapter_find_by_identifier(remain)) == NULL) {
-    pthread_mutex_unlock(&global_lock);
-    return 404;
-  }
-
-  in = entries != NULL ? htsmsg_json_deserialize(entries) : NULL;
-
-  if(!strcmp(op, "get")) {
-
-    LIST_FOREACH(t, &va->va_services, s_group_link)
-      count++;
-    tvec = alloca(sizeof(service_t *) * count);
-    LIST_FOREACH(t, &va->va_services, s_group_link)
-      tvec[i++] = t;
-
-    out = htsmsg_create_map();
-    array = htsmsg_create_list();
-
-    qsort(tvec, count, sizeof(service_t *), v4l_servicecmp);
-
-    for(i = 0; i < count; i++)
-      htsmsg_add_msg(array, NULL, build_record_v4l(tvec[i]));
-
-    htsmsg_add_msg(out, "entries", array);
-
-  } else if(!strcmp(op, "update")) {
-    if(in != NULL) {
-      extjs_service_update(in);      // Generic service parameters
-      service_update_v4l(in);  // V4L speicifc
-    }
-
-    out = htsmsg_create_map();
-
-  } else if(!strcmp(op, "create")) {
-
-    out = build_record_v4l(v4l_service_find(va, NULL, 1));
-
-  } else if(!strcmp(op, "delete")) {
-    if(in != NULL)
-      extjs_service_delete(in);
-
-    out = htsmsg_create_map();
-
-  } else {
-    pthread_mutex_unlock(&global_lock);
-    htsmsg_destroy(in);
-    return HTTP_STATUS_BAD_REQUEST;
-  }
-
-  htsmsg_destroy(in);
-
-  pthread_mutex_unlock(&global_lock);
-
-  htsmsg_json_serialize(out, hq, 0);
-  htsmsg_destroy(out);
-  http_output_content(hc, "text/x-json; charset=UTF-8");
-  return 0;
-}
-
-#if 0
-
-/**
- *
- */
-void
-extjs_list_v4l_adapters(htsmsg_t *array)
-{
-  v4l_adapter_t *va;
-
-  TAILQ_FOREACH(va, &v4l_adapters, va_global_link) 
-    htsmsg_add_msg(array, NULL, v4l_adapter_build_msg(va));
-}
-#endif
-
-
-/**
- * WEB user interface
- */
-void
-extjs_start_v4l(void)
-{
-  http_path_add("/v4l/adapter", 
-               NULL, extjs_v4ladapter, ACCESS_ADMIN);
-
-  http_path_add("/v4l/services", 
-               NULL, extjs_v4lservices, ACCESS_ADMIN);
-}
index 32cb7cfb5ba003bd3856003201539f1a148ea833..45b93deaadd0f9aaac5fcaa1df52b50179155891 100644 (file)
@@ -31,7 +31,7 @@ webui_api_handler
 {
   int r;
   http_arg_t *ha;
-  htsmsg_t *args, *resp;
+  htsmsg_t *args, *resp = NULL;
   const char *a  = http_arg_get(&hc->hc_req_args, "args");
   const char *op = http_arg_get(&hc->hc_req_args, "method");
   
@@ -74,9 +74,10 @@ webui_api_handler
       default:
         r = HTTP_STATUS_BAD_REQUEST;
     }
+  }
 
   /* Output response */
-  } else {
+  if (resp) {
     htsmsg_json_serialize(resp, &hc->hc_reply, 0);
     http_output_content(hc, "text/x-json; charset=UTF-8");
     htsmsg_destroy(resp);