diff --git a/Makefile b/Makefile
index aaaad9da..a80ecbcd 100644
--- a/Makefile
+++ b/Makefile
@@ -109,10 +109,12 @@ SRCS = src/version.c \
src/tvhtime.c \
src/descrambler/descrambler.c \
src/service_mapper.c \
+ src/input.c \
SRCS += \
src/api.c \
src/api/api_idnode.c \
+ src/api/api_input.c \
src/api/api_channel.c \
src/api/api_service.c \
src/api/api_mpegts.c \
diff --git a/src/api.c b/src/api.c
index 2a0b4b67..16895d9c 100644
--- a/src/api.c
+++ b/src/api.c
@@ -116,6 +116,7 @@ void api_init ( void )
/* Subsystems */
api_idnode_init();
+ api_input_init();
api_mpegts_init();
api_service_init();
api_channel_init();
diff --git a/src/api.h b/src/api.h
index ca4be19e..a3897540 100644
--- a/src/api.h
+++ b/src/api.h
@@ -57,9 +57,10 @@ int api_exec ( const char *subsystem, htsmsg_t *args, htsmsg_t **resp );
*/
void api_init ( void );
void api_idnode_init ( void );
-void api_mpegts_init ( void );
+void api_input_init ( void );
void api_service_init ( void );
void api_channel_init ( void );
+void api_mpegts_init ( void );
/*
* IDnode
diff --git a/src/api/api_input.c b/src/api/api_input.c
new file mode 100644
index 00000000..f6cef7db
--- /dev/null
+++ b/src/api/api_input.c
@@ -0,0 +1,71 @@
+/*
+ * API - channel related calls
+ *
+ * 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 .
+ */
+
+#ifndef __TVH_API_INPUT_H__
+#define __TVH_API_INPUT_H__
+
+#include "tvheadend.h"
+#include "idnode.h"
+#include "input.h"
+#include "access.h"
+#include "api.h"
+
+static int
+api_input_status
+ ( void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
+{
+ int c = 0;
+ htsmsg_t *l, *e;
+ tvh_input_t *ti;
+ tvh_input_stream_t *st;
+ tvh_input_stream_list_t stl = { 0 };
+
+ TVH_INPUT_FOREACH(ti)
+ ti->ti_get_streams(ti, &stl);
+
+ l = htsmsg_create_list();
+ while ((st = LIST_FIRST(&stl))) {
+ e = tvh_input_stream_create_msg(st);
+ htsmsg_add_msg(l, NULL, e);
+ tvh_input_stream_destroy(st);
+ LIST_REMOVE(st, link);
+ free(st);
+ c++;
+ }
+
+ *resp = htsmsg_create_map();
+ htsmsg_add_msg(*resp, "entries", l);
+ htsmsg_add_u32(*resp, "totalCount", c);
+
+ return 0;
+}
+
+void api_input_init ( void )
+{
+ static api_hook_t ah[] = {
+ { "input/status", ACCESS_ANONYMOUS, api_input_status, NULL },
+// { "input/tree", ACCESS_ANONYMOUS, NULL, NULL },
+ { NULL },
+ };
+
+ api_register_all(ah);
+}
+
+
+#endif /* __TVH_API_INPUT_H__ */
diff --git a/src/descrambler/capmt.c b/src/descrambler/capmt.c
index 0b4b5656..98237940 100644
--- a/src/descrambler/capmt.c
+++ b/src/descrambler/capmt.c
@@ -654,7 +654,7 @@ capmt_table_input(struct th_descrambler *td, struct service *s,
return;
if (!t->s_dvb_active_input) return;
lfe = (linuxdvb_frontend_t*)t->s_dvb_active_input;
- if (!idnode_is_instance(&lfe->mi_id, &linuxdvb_frontend_class))
+ if (!idnode_is_instance(&lfe->ti_id, &linuxdvb_frontend_class))
return;
adapter_num = ((linuxdvb_adapter_t*)lfe->lh_parent)->la_number;
@@ -893,7 +893,7 @@ capmt_service_start(service_t *s)
return;
if (!t->s_dvb_active_input) return;
lfe = (linuxdvb_frontend_t*)t->s_dvb_active_input;
- if (!idnode_is_instance(&lfe->mi_id, &linuxdvb_frontend_class))
+ if (!idnode_is_instance(&lfe->ti_id, &linuxdvb_frontend_class))
return;
tuner = ((linuxdvb_adapter_t*)lfe->lh_parent)->la_number;
diff --git a/src/input.h b/src/input.h
index a377d7bc..7bd63ba2 100644
--- a/src/input.h
+++ b/src/input.h
@@ -19,6 +19,61 @@
#ifndef __TVH_INPUT_H__
#define __TVH_INPUT_H__
+#include "idnode.h"
+#include "queue.h"
+
+/*
+ * Input stream structure - used for getting statistics about active streams
+ */
+typedef struct tvh_input_stream_stats
+{
+ int signal; ///< Signal level (0-100)
+ int ber; ///< Bit error rate (0-100?)
+ int unc; ///< Uncorrectable errors
+ int snr; ///< Signal 2 Noise (dB)
+ int bps; ///< Bandwidth (bps)
+} tvh_input_stream_stats_t;
+
+typedef struct tvh_input_stream {
+
+ LIST_ENTRY(tvh_input_stream) link;
+
+ char *uuid; ///< Unique ID of the entry (used for updates)
+ char *input_name; ///< Name of the parent input
+ char *stream_name; ///< Name for this stream
+ int subs_count; ///< Number of subcscriptions
+ int max_weight; ///< Current max weight
+
+ tvh_input_stream_stats_t stats;
+
+} tvh_input_stream_t;
+
+typedef LIST_HEAD(,tvh_input_stream) tvh_input_stream_list_t;
+
+/*
+ * Generic input super-class
+ */
+typedef struct tvh_input {
+ idnode_t ti_id;
+
+ LIST_ENTRY(tvh_input) ti_link;
+
+ void (*ti_get_streams) (struct tvh_input *, tvh_input_stream_list_t*);
+
+} tvh_input_t;
+
+typedef LIST_HEAD(,tvh_input) tvh_input_list_t;
+tvh_input_list_t tvh_inputs;
+
+#define TVH_INPUT_FOREACH(x) LIST_FOREACH(x, &tvh_inputs, ti_link)
+
+void input_init ( void );
+
+htsmsg_t * tvh_input_stream_create_msg ( tvh_input_stream_t *st );
+
+void tvh_input_stream_destroy ( tvh_input_stream_t *st );
+
+
#if ENABLE_MPEGPS
#include "input/mpegps.h"
#endif
@@ -36,6 +91,4 @@
#endif
#endif
-void input_init ( void );
-
#endif /* __TVH_INPUT_H__ */
diff --git a/src/input/mpegts.h b/src/input/mpegts.h
index cb71fb66..95e7f9dd 100644
--- a/src/input/mpegts.h
+++ b/src/input/mpegts.h
@@ -20,6 +20,7 @@
#ifndef __TVH_MPEGTS_H__
#define __TVH_MPEGTS_H__
+#include "input.h"
#include "service.h"
#include "mpegts/dvb.h"
@@ -374,8 +375,9 @@ struct mpegts_mux_instance
LIST_HEAD(,th_subscription) mmi_subs;
- // TODO: remove this
- int mmi_tune_failed; // this is really DVB
+ tvh_input_stream_stats_t mmi_stats;
+
+ int mmi_tune_failed;
void (*mmi_delete) (mpegts_mux_instance_t *mmi);
};
@@ -390,7 +392,7 @@ struct mpegts_mux_sub
/* Input source */
struct mpegts_input
{
- idnode_t mi_id;
+ tvh_input_t;
int mi_enabled;
@@ -407,6 +409,11 @@ struct mpegts_input
LIST_HEAD(,mpegts_mux_instance) mi_mux_instances;
+ /*
+ * Status
+ */
+ gtimer_t mi_status_timer;
+
/*
* Input processing
*/
@@ -416,8 +423,6 @@ struct mpegts_input
LIST_HEAD(,service) mi_transports;
- int mi_bytes;
-
struct mpegts_table_feed_queue mi_table_feed;
pthread_cond_t mi_table_feed_cond; // Bound to mi_delivery_mutex
@@ -484,6 +489,8 @@ void mpegts_input_set_network ( mpegts_input_t *mi, mpegts_network_t *mn );
void mpegts_input_open_service ( mpegts_input_t *mi, mpegts_service_t *s, int init );
void mpegts_input_close_service ( mpegts_input_t *mi, mpegts_service_t *s );
+void mpegts_input_status_timer ( void *p );
+
void mpegts_network_register_builder
( const idclass_t *idc,
mpegts_network_t *(*build)(const idclass_t *idc, htsmsg_t *conf) );
diff --git a/src/input/mpegts/linuxdvb/linuxdvb_adapter.c b/src/input/mpegts/linuxdvb/linuxdvb_adapter.c
index c4407c3b..b2fadf60 100644
--- a/src/input/mpegts/linuxdvb/linuxdvb_adapter.c
+++ b/src/input/mpegts/linuxdvb/linuxdvb_adapter.c
@@ -71,7 +71,7 @@ linuxdvb_adapter_save ( linuxdvb_adapter_t *la, htsmsg_t *m )
htsmsg_t *l;
linuxdvb_hardware_t *lh;
- idnode_save(&la->mi_id, m);
+ idnode_save(&la->ti_id, m);
htsmsg_add_u32(m, "number", la->la_number);
if (la->la_rootpath)
htsmsg_add_str(m, "rootpath", la->la_rootpath);
@@ -81,7 +81,7 @@ linuxdvb_adapter_save ( linuxdvb_adapter_t *la, htsmsg_t *m )
LIST_FOREACH(lh, &la->lh_children, lh_parent_link) {
htsmsg_t *e = htsmsg_create_map();
linuxdvb_frontend_save((linuxdvb_frontend_t*)lh, e);
- htsmsg_add_msg(l, idnode_uuid_as_str(&lh->mi_id), e);
+ htsmsg_add_msg(l, idnode_uuid_as_str(&lh->ti_id), e);
}
htsmsg_add_msg(m, "frontends", l);
}
@@ -118,7 +118,7 @@ linuxdvb_adapter_create0
linuxdvb_adapter_t *la;
la = calloc(1, sizeof(linuxdvb_adapter_t));
- if (idnode_insert(&la->mi_id, uuid, &linuxdvb_adapter_class)) {
+ if (idnode_insert(&la->ti_id, uuid, &linuxdvb_adapter_class)) {
free(la);
return NULL;
}
@@ -131,7 +131,7 @@ linuxdvb_adapter_create0
if (!conf)
return la;
- idnode_load(&la->mi_id, conf);
+ idnode_load(&la->ti_id, conf);
if (!htsmsg_get_u32(conf, "number", &u32))
la->la_number = u32;
if ((str = htsmsg_get_str(conf, "rootpath")))
diff --git a/src/input/mpegts/linuxdvb/linuxdvb_device.c b/src/input/mpegts/linuxdvb/linuxdvb_device.c
index 37b4b0e8..9e288f0d 100644
--- a/src/input/mpegts/linuxdvb/linuxdvb_device.c
+++ b/src/input/mpegts/linuxdvb/linuxdvb_device.c
@@ -175,20 +175,20 @@ void linuxdvb_device_save ( linuxdvb_device_t *ld )
m = htsmsg_create_map();
- idnode_save(&ld->mi_id, m);
+ idnode_save(&ld->ti_id, m);
/* Adapters */
l = htsmsg_create_map();
LIST_FOREACH(lh, &ld->lh_children, lh_parent_link) {
e = htsmsg_create_map();
linuxdvb_adapter_save((linuxdvb_adapter_t*)lh, e);
- htsmsg_add_msg(l, idnode_uuid_as_str(&lh->mi_id), e);
+ htsmsg_add_msg(l, idnode_uuid_as_str(&lh->ti_id), e);
}
htsmsg_add_msg(m, "adapters", l);
/* Save */
hts_settings_save(m, "input/linuxdvb/devices/%s",
- idnode_uuid_as_str(&ld->mi_id));
+ idnode_uuid_as_str(&ld->ti_id));
}
const idclass_t linuxdvb_device_class =
@@ -226,7 +226,7 @@ linuxdvb_device_create0 ( const char *uuid, htsmsg_t *conf )
/* Create */
ld = calloc(1, sizeof(linuxdvb_device_t));
- if (idnode_insert(&ld->mi_id, uuid, &linuxdvb_device_class)) {
+ if (idnode_insert(&ld->ti_id, uuid, &linuxdvb_device_class)) {
free(ld);
return NULL;
}
@@ -240,7 +240,7 @@ linuxdvb_device_create0 ( const char *uuid, htsmsg_t *conf )
return ld;
/* Load config */
- idnode_load(&ld->mi_id, conf);
+ idnode_load(&ld->ti_id, conf);
get_min_dvb_adapter(&ld->ld_devid);
/* Adapters */
diff --git a/src/input/mpegts/linuxdvb/linuxdvb_frontend.c b/src/input/mpegts/linuxdvb/linuxdvb_frontend.c
index e4de3eff..7dc76866 100644
--- a/src/input/mpegts/linuxdvb/linuxdvb_frontend.c
+++ b/src/input/mpegts/linuxdvb/linuxdvb_frontend.c
@@ -1,5 +1,4 @@
/*
-rk_class
* Tvheadend - Linux DVB frontend
*
* Copyright (C) 2013 Adam Sutton
@@ -461,42 +460,11 @@ linuxdvb_frontend_open_all
}
}
-static void
-linuxdvb_frontend_monitor_stats ( linuxdvb_frontend_t *lfe, const char *name )
-{
- int bw;
- htsmsg_t *m, *l, *e;
- mpegts_mux_instance_t *mmi;
-
- /* Send message */
- m = htsmsg_create_map();
- htsmsg_add_str(m, "uuid", idnode_uuid_as_str(&lfe->mi_id));
- htsmsg_add_str(m, "name", name);
- htsmsg_add_str(m, "type", "linuxdvb");
-
- /* Mux list */
- if ((mmi = LIST_FIRST(&lfe->mi_mux_active))) {
- char buf[256];
- l = htsmsg_create_list();
- e = htsmsg_create_map();
- mmi->mmi_mux->mm_display_name(mmi->mmi_mux, buf, sizeof(buf));
- htsmsg_add_str(e, "name", buf);
- htsmsg_add_u32(e, "bytes", 0); // TODO
- // TODO: signal info
- htsmsg_add_msg(l, NULL, e);
- htsmsg_add_msg(m, "muxes", l);
- }
-
- /* Total data */
- bw = atomic_exchange(&lfe->mi_bytes, 0);
- htsmsg_add_u32(m, "bytes", bw);
-
- notify_by_msg("input", m);
-}
-
static void
linuxdvb_frontend_monitor ( void *aux )
{
+ uint16_t u16;
+ uint32_t u32;
char buf[256];
linuxdvb_frontend_t *lfe = aux;
mpegts_mux_instance_t *mmi = LIST_FIRST(&lfe->mi_mux_active);
@@ -573,8 +541,15 @@ linuxdvb_frontend_monitor ( void *aux )
}
}
- /* Monitor stats */
- linuxdvb_frontend_monitor_stats(lfe, buf);
+ /* Statistics */
+ if (!ioctl(lfe->lfe_fe_fd, FE_READ_SIGNAL_STRENGTH, &u16))
+ mmi->mmi_stats.signal = u16;
+ if (!ioctl(lfe->lfe_fe_fd, FE_READ_BER, &u32))
+ mmi->mmi_stats.ber = u32;
+ if (!ioctl(lfe->lfe_fe_fd, FE_READ_SNR, &u16))
+ mmi->mmi_stats.snr = u16;
+ if (!ioctl(lfe->lfe_fe_fd, FE_READ_UNCORRECTED_BLOCKS, &u32))
+ mmi->mmi_stats.unc = u32;
}
static void *
diff --git a/src/input/mpegts/linuxdvb/linuxdvb_hardware.c b/src/input/mpegts/linuxdvb/linuxdvb_hardware.c
index 79df2c5a..6150f279 100644
--- a/src/input/mpegts/linuxdvb/linuxdvb_hardware.c
+++ b/src/input/mpegts/linuxdvb/linuxdvb_hardware.c
@@ -35,7 +35,7 @@ linuxdvb_hardware_enumerate ( linuxdvb_hardware_list_t *list )
linuxdvb_hardware_t *lh;
idnode_set_t *set = idnode_set_create();
LIST_FOREACH(lh, list, lh_parent_link)
- idnode_set_add(set, &lh->mi_id, NULL);
+ idnode_set_add(set, &lh->ti_id, NULL);
return set;
}
diff --git a/src/input/mpegts/linuxdvb/linuxdvb_satconf.c b/src/input/mpegts/linuxdvb/linuxdvb_satconf.c
index eee864dc..b9a95637 100644
--- a/src/input/mpegts/linuxdvb/linuxdvb_satconf.c
+++ b/src/input/mpegts/linuxdvb/linuxdvb_satconf.c
@@ -91,7 +91,7 @@ linuxdvb_satconf_class_frontend_get ( void *o )
static const char *s;
linuxdvb_satconf_t *ls = o;
if (ls->ls_frontend)
- s = idnode_uuid_as_str(&ls->ls_frontend->mi_id);
+ s = idnode_uuid_as_str(&ls->ls_frontend->ti_id);
else
s = NULL;
return &s;
@@ -123,7 +123,7 @@ linuxdvb_satconf_class_frontend_enum (void *o)
for (i = 0; i < is->is_count; i++) {
mpegts_input_t *mi = (mpegts_input_t*)is->is_array[i];
htsmsg_t *e = htsmsg_create_map();
- htsmsg_add_str(e, "key", idnode_uuid_as_str(&mi->mi_id));
+ htsmsg_add_str(e, "key", idnode_uuid_as_str(&mi->ti_id));
*buf = 0;
mi->mi_display_name(mi, buf, sizeof(buf));
htsmsg_add_str(e, "val", buf);
@@ -585,7 +585,7 @@ linuxdvb_diseqc_class_save ( idnode_t *o )
{
linuxdvb_diseqc_t *ld = (linuxdvb_diseqc_t*)o;
if (ld->ld_satconf)
- linuxdvb_satconf_class_save(&ld->ld_satconf->mi_id);
+ linuxdvb_satconf_class_save(&ld->ld_satconf->ti_id);
}
const idclass_t linuxdvb_diseqc_class =
diff --git a/src/input/mpegts/mpegts_input.c b/src/input/mpegts/mpegts_input.c
index 429d80a1..090de1f8 100644
--- a/src/input/mpegts/mpegts_input.c
+++ b/src/input/mpegts/mpegts_input.c
@@ -22,6 +22,7 @@
#include "streaming.h"
#include "subscriptions.h"
#include "atomic.h"
+#include "notify.h"
#include
#include
@@ -164,8 +165,15 @@ static void
mpegts_input_started_mux
( mpegts_input_t *mi, mpegts_mux_instance_t *mmi )
{
+ /* Arm timer */
+ if (LIST_FIRST(&mi->mi_mux_active) == NULL)
+ gtimer_arm(&mi->mi_status_timer, mpegts_input_status_timer,
+ mi, 1);
+
+ /* Update */
mmi->mmi_mux->mm_active = mmi;
LIST_INSERT_HEAD(&mi->mi_mux_active, mmi, mmi_active_link);
+ notify_reload("input_status");
}
static void
@@ -177,6 +185,10 @@ mpegts_input_stopped_mux
mmi->mmi_mux->mm_active = NULL;
LIST_REMOVE(mmi, mmi_active_link);
+ /* Disarm timer */
+ if (LIST_FIRST(&mi->mi_mux_active) == NULL)
+ gtimer_disarm(&mi->mi_status_timer);
+
mi->mi_display_name(mi, buf, sizeof(buf));
tvhtrace("mpegts", "%s - flush subscribers", buf);
s = LIST_FIRST(&mi->mi_transports);
@@ -185,6 +197,7 @@ mpegts_input_stopped_mux
service_remove_subscriber(s, NULL, SM_CODE_SUBSCRIPTION_OVERRIDDEN);
s = LIST_NEXT(s, s_active_link);
}
+ notify_reload("input_status");
}
static int
@@ -290,7 +303,7 @@ mpegts_input_recv_packets
pthread_mutex_unlock(&mi->mi_delivery_mutex);
/* Bandwidth monitoring */
- atomic_add(&mi->mi_bytes, i);
+ atomic_add(&mmi->mmi_stats.bps, i);
/* Reset buffer */
if (len) memmove(tsb, tsb+i, len);
@@ -371,6 +384,59 @@ mpegts_input_flush_mux
pthread_mutex_unlock(&mi->mi_delivery_mutex);
}
+static void
+mpegts_input_stream_status
+ ( mpegts_mux_instance_t *mmi, tvh_input_stream_t *st )
+{
+ int s = 0, w = 0;
+ char buf[512];
+ mmi->mmi_mux->mm_display_name(mmi->mmi_mux, buf, sizeof(buf));
+ st->uuid = strdup(idnode_uuid_as_str(&mmi->mmi_id));
+ st->input_name = strdup(mmi->mmi_input->mi_displayname?:"");
+ st->stream_name = strdup(buf);
+ st->subs_count = s;
+ st->max_weight = w;
+ st->stats = mmi->mmi_stats;
+ st->stats.bps = atomic_exchange(&mmi->mmi_stats.bps, 0) * 8;
+}
+
+static void
+mpegts_input_get_streams
+ ( tvh_input_t *i, tvh_input_stream_list_t *isl )
+{
+ tvh_input_stream_t *st;
+ mpegts_input_t *mi = (mpegts_input_t*)i;
+ mpegts_mux_instance_t *mmi;
+
+ LIST_FOREACH(mmi, &mi->mi_mux_active, mmi_active_link) {
+ st = calloc(1, sizeof(tvh_input_stream_t));
+ mpegts_input_stream_status(mmi, st);
+ LIST_INSERT_HEAD(isl, st, link);
+ }
+}
+
+/* **************************************************************************
+ * Status monitoring
+ * *************************************************************************/
+
+void
+mpegts_input_status_timer ( void *p )
+{
+ tvh_input_stream_t st;
+ mpegts_input_t *mi = p;
+ mpegts_mux_instance_t *mmi;
+ htsmsg_t *e;
+ LIST_FOREACH(mmi, &mi->mi_mux_active, mmi_active_link) {
+ memset(&st, 0, sizeof(st));
+ mpegts_input_stream_status(mmi, &st);
+ e = tvh_input_stream_create_msg(&st);
+ htsmsg_add_u32(e, "update", 1);
+ notify_by_msg("input_status", e);
+ tvh_input_stream_destroy(&st);
+ }
+ gtimer_arm(&mi->mi_status_timer, mpegts_input_status_timer, mi, 1);
+}
+
/* **************************************************************************
* Creation/Config
* *************************************************************************/
@@ -383,7 +449,8 @@ mpegts_input_create0
( mpegts_input_t *mi, const idclass_t *class, const char *uuid,
htsmsg_t *c )
{
- idnode_insert(&mi->mi_id, uuid, class);
+ idnode_insert(&mi->ti_id, uuid, class);
+ LIST_INSERT_HEAD(&tvh_inputs, (tvh_input_t*)mi, ti_link);
/* Defaults */
mi->mi_is_enabled = mpegts_input_is_enabled;
@@ -398,6 +465,7 @@ mpegts_input_create0
mi->mi_started_mux = mpegts_input_started_mux;
mi->mi_stopped_mux = mpegts_input_stopped_mux;
mi->mi_has_subscription = mpegts_input_has_subscription;
+ mi->ti_get_streams = mpegts_input_get_streams;
/* Index */
mi->mi_instance = ++mpegts_input_idx;
@@ -417,7 +485,7 @@ mpegts_input_create0
/* Load config */
if (c)
- idnode_load(&mi->mi_id, c);
+ idnode_load(&mi->ti_id, c);
return mi;
}
@@ -425,7 +493,7 @@ mpegts_input_create0
void
mpegts_input_save ( mpegts_input_t *mi, htsmsg_t *m )
{
- idnode_save(&mi->mi_id, m);
+ idnode_save(&mi->ti_id, m);
}
void
diff --git a/src/webui/static/app/status.js b/src/webui/static/app/status.js
index 2caa8fb7..32aa9c74 100644
--- a/src/webui/static/app/status.js
+++ b/src/webui/static/app/status.js
@@ -136,9 +136,61 @@ tvheadend.status_subs = function() {
/**
- *
+ * Streams
*/
-tvheadend.status_adapters = function() {
+tvheadend.status_streams = function() {
+
+ var stream_store = new Ext.data.JsonStore({
+ root : 'entries',
+ totalProperty : 'totalCount',
+ fields : [ {
+ name : 'uuid'
+ }, {
+ name : 'input'
+ }, {
+ name : 'username'
+ }, {
+ name : 'stream'
+ }, {
+ name : 'subs'
+ }, {
+ name : 'weight'
+ }, {
+ name : 'signal'
+ }, {
+ name : 'ber'
+ }, {
+ name : 'unc'
+ }, {
+ name : 'snr'
+ }, {
+ name : 'bps'
+ },
+ ],
+ url : 'api/input/status',
+ autoLoad : true,
+ id : 'uuid'
+ });
+
+ tvheadend.comet.on('input_status', function(m){
+ if (m.reload != null) stream_store.reload();
+ if (m.update != null) {
+ var r = stream_store.getById(m.uuid);
+ if (r) {
+ r.data.subs = m.subs;
+ r.data.weight = m.weight;
+ r.data.signal = m.signal;
+ r.data.ber = m.ber;
+ r.data.unc = m.unc;
+ r.data.snr = m.snr;
+ r.data.bps = m.bps;
+ stream_store.afterEdit(r);
+ stream_store.fireEvent('updated', stream_store, r, Ext.data.Record.COMMIT);
+ } else {
+ stream_store.reload();
+ }
+ }
+ });
var signal = new Ext.ux.grid.ProgressColumn({
header : "Signal Strength",
@@ -149,30 +201,30 @@ tvheadend.status_adapters = function() {
});
function renderBw(value) {
- return parseInt(value / 125);
+ return parseInt(value / 1024);
}
var cm = new Ext.grid.ColumnModel([{
- width : 50,
- header : "Name",
- dataIndex : 'name'
- },{
- width : 50,
- header : "Hardware device",
- dataIndex : 'path'
+ width : 100,
+ header : "Input",
+ dataIndex : 'input'
},{
width : 100,
- header : "Currently tuned to",
- dataIndex : 'currentMux'
+ header : "Stream",
+ dataIndex : 'stream'
+ },{
+ width : 50,
+ header : "Subs #",
+ dataIndex : 'subs'
+ },{
+ width : 50,
+ header : "Weight",
+ dataIndex : 'weight'
},{
width : 100,
header : "Bandwidth (kb/s)",
- dataIndex : 'bw',
+ dataIndex : 'bps',
renderer: renderBw
- },{
- width : 50,
- header : "Used for",
- dataIndex : 'reason'
},{
width : 50,
header : "Bit error rate",
@@ -180,7 +232,7 @@ tvheadend.status_adapters = function() {
},{
width : 50,
header : "Uncorrected bit error rate",
- dataIndex : 'uncavg'
+ dataIndex : 'unc'
},{
width : 50,
header : "SNR",
@@ -199,9 +251,9 @@ tvheadend.status_adapters = function() {
loadMask : true,
stripeRows : true,
disableSelection : true,
- title : 'Adapters',
+ title : 'Stream',
iconCls : 'hardware',
- store : tvheadend.tvAdapterStore,
+ store : stream_store,
cm : cm,
flex: 1,
viewConfig : {
@@ -218,7 +270,7 @@ tvheadend.status = function() {
layout : 'vbox',
title : 'Status',
iconCls : 'eye',
- items : [ new tvheadend.status_subs, new tvheadend.status_adapters ]
+ items : [ new tvheadend.status_subs, new tvheadend.status_streams ]
});
return panel;