status: added back in basic status info
It will now show subscriptions and streams (tuners/muxes combined).
This commit is contained in:
parent
f16c29559e
commit
8ac1b3d7ed
14 changed files with 314 additions and 84 deletions
2
Makefile
2
Makefile
|
@ -109,10 +109,12 @@ SRCS = src/version.c \
|
||||||
src/tvhtime.c \
|
src/tvhtime.c \
|
||||||
src/descrambler/descrambler.c \
|
src/descrambler/descrambler.c \
|
||||||
src/service_mapper.c \
|
src/service_mapper.c \
|
||||||
|
src/input.c \
|
||||||
|
|
||||||
SRCS += \
|
SRCS += \
|
||||||
src/api.c \
|
src/api.c \
|
||||||
src/api/api_idnode.c \
|
src/api/api_idnode.c \
|
||||||
|
src/api/api_input.c \
|
||||||
src/api/api_channel.c \
|
src/api/api_channel.c \
|
||||||
src/api/api_service.c \
|
src/api/api_service.c \
|
||||||
src/api/api_mpegts.c \
|
src/api/api_mpegts.c \
|
||||||
|
|
|
@ -116,6 +116,7 @@ void api_init ( void )
|
||||||
|
|
||||||
/* Subsystems */
|
/* Subsystems */
|
||||||
api_idnode_init();
|
api_idnode_init();
|
||||||
|
api_input_init();
|
||||||
api_mpegts_init();
|
api_mpegts_init();
|
||||||
api_service_init();
|
api_service_init();
|
||||||
api_channel_init();
|
api_channel_init();
|
||||||
|
|
|
@ -57,9 +57,10 @@ int api_exec ( const char *subsystem, htsmsg_t *args, htsmsg_t **resp );
|
||||||
*/
|
*/
|
||||||
void api_init ( void );
|
void api_init ( void );
|
||||||
void api_idnode_init ( void );
|
void api_idnode_init ( void );
|
||||||
void api_mpegts_init ( void );
|
void api_input_init ( void );
|
||||||
void api_service_init ( void );
|
void api_service_init ( void );
|
||||||
void api_channel_init ( void );
|
void api_channel_init ( void );
|
||||||
|
void api_mpegts_init ( void );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* IDnode
|
* IDnode
|
||||||
|
|
71
src/api/api_input.c
Normal file
71
src/api/api_input.c
Normal file
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#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__ */
|
|
@ -654,7 +654,7 @@ capmt_table_input(struct th_descrambler *td, struct service *s,
|
||||||
return;
|
return;
|
||||||
if (!t->s_dvb_active_input) return;
|
if (!t->s_dvb_active_input) return;
|
||||||
lfe = (linuxdvb_frontend_t*)t->s_dvb_active_input;
|
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;
|
return;
|
||||||
adapter_num = ((linuxdvb_adapter_t*)lfe->lh_parent)->la_number;
|
adapter_num = ((linuxdvb_adapter_t*)lfe->lh_parent)->la_number;
|
||||||
|
|
||||||
|
@ -893,7 +893,7 @@ capmt_service_start(service_t *s)
|
||||||
return;
|
return;
|
||||||
if (!t->s_dvb_active_input) return;
|
if (!t->s_dvb_active_input) return;
|
||||||
lfe = (linuxdvb_frontend_t*)t->s_dvb_active_input;
|
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;
|
return;
|
||||||
tuner = ((linuxdvb_adapter_t*)lfe->lh_parent)->la_number;
|
tuner = ((linuxdvb_adapter_t*)lfe->lh_parent)->la_number;
|
||||||
|
|
||||||
|
|
57
src/input.h
57
src/input.h
|
@ -19,6 +19,61 @@
|
||||||
#ifndef __TVH_INPUT_H__
|
#ifndef __TVH_INPUT_H__
|
||||||
#define __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
|
#if ENABLE_MPEGPS
|
||||||
#include "input/mpegps.h"
|
#include "input/mpegps.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -36,6 +91,4 @@
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void input_init ( void );
|
|
||||||
|
|
||||||
#endif /* __TVH_INPUT_H__ */
|
#endif /* __TVH_INPUT_H__ */
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#ifndef __TVH_MPEGTS_H__
|
#ifndef __TVH_MPEGTS_H__
|
||||||
#define __TVH_MPEGTS_H__
|
#define __TVH_MPEGTS_H__
|
||||||
|
|
||||||
|
#include "input.h"
|
||||||
#include "service.h"
|
#include "service.h"
|
||||||
#include "mpegts/dvb.h"
|
#include "mpegts/dvb.h"
|
||||||
|
|
||||||
|
@ -374,8 +375,9 @@ struct mpegts_mux_instance
|
||||||
|
|
||||||
LIST_HEAD(,th_subscription) mmi_subs;
|
LIST_HEAD(,th_subscription) mmi_subs;
|
||||||
|
|
||||||
// TODO: remove this
|
tvh_input_stream_stats_t mmi_stats;
|
||||||
int mmi_tune_failed; // this is really DVB
|
|
||||||
|
int mmi_tune_failed;
|
||||||
|
|
||||||
void (*mmi_delete) (mpegts_mux_instance_t *mmi);
|
void (*mmi_delete) (mpegts_mux_instance_t *mmi);
|
||||||
};
|
};
|
||||||
|
@ -390,7 +392,7 @@ struct mpegts_mux_sub
|
||||||
/* Input source */
|
/* Input source */
|
||||||
struct mpegts_input
|
struct mpegts_input
|
||||||
{
|
{
|
||||||
idnode_t mi_id;
|
tvh_input_t;
|
||||||
|
|
||||||
int mi_enabled;
|
int mi_enabled;
|
||||||
|
|
||||||
|
@ -407,6 +409,11 @@ struct mpegts_input
|
||||||
|
|
||||||
LIST_HEAD(,mpegts_mux_instance) mi_mux_instances;
|
LIST_HEAD(,mpegts_mux_instance) mi_mux_instances;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Status
|
||||||
|
*/
|
||||||
|
gtimer_t mi_status_timer;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Input processing
|
* Input processing
|
||||||
*/
|
*/
|
||||||
|
@ -416,8 +423,6 @@ struct mpegts_input
|
||||||
LIST_HEAD(,service) mi_transports;
|
LIST_HEAD(,service) mi_transports;
|
||||||
|
|
||||||
|
|
||||||
int mi_bytes;
|
|
||||||
|
|
||||||
struct mpegts_table_feed_queue mi_table_feed;
|
struct mpegts_table_feed_queue mi_table_feed;
|
||||||
pthread_cond_t mi_table_feed_cond; // Bound to mi_delivery_mutex
|
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_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_close_service ( mpegts_input_t *mi, mpegts_service_t *s );
|
||||||
|
|
||||||
|
void mpegts_input_status_timer ( void *p );
|
||||||
|
|
||||||
void mpegts_network_register_builder
|
void mpegts_network_register_builder
|
||||||
( const idclass_t *idc,
|
( const idclass_t *idc,
|
||||||
mpegts_network_t *(*build)(const idclass_t *idc, htsmsg_t *conf) );
|
mpegts_network_t *(*build)(const idclass_t *idc, htsmsg_t *conf) );
|
||||||
|
|
|
@ -71,7 +71,7 @@ linuxdvb_adapter_save ( linuxdvb_adapter_t *la, htsmsg_t *m )
|
||||||
htsmsg_t *l;
|
htsmsg_t *l;
|
||||||
linuxdvb_hardware_t *lh;
|
linuxdvb_hardware_t *lh;
|
||||||
|
|
||||||
idnode_save(&la->mi_id, m);
|
idnode_save(&la->ti_id, m);
|
||||||
htsmsg_add_u32(m, "number", la->la_number);
|
htsmsg_add_u32(m, "number", la->la_number);
|
||||||
if (la->la_rootpath)
|
if (la->la_rootpath)
|
||||||
htsmsg_add_str(m, "rootpath", 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) {
|
LIST_FOREACH(lh, &la->lh_children, lh_parent_link) {
|
||||||
htsmsg_t *e = htsmsg_create_map();
|
htsmsg_t *e = htsmsg_create_map();
|
||||||
linuxdvb_frontend_save((linuxdvb_frontend_t*)lh, e);
|
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);
|
htsmsg_add_msg(m, "frontends", l);
|
||||||
}
|
}
|
||||||
|
@ -118,7 +118,7 @@ linuxdvb_adapter_create0
|
||||||
linuxdvb_adapter_t *la;
|
linuxdvb_adapter_t *la;
|
||||||
|
|
||||||
la = calloc(1, sizeof(linuxdvb_adapter_t));
|
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);
|
free(la);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -131,7 +131,7 @@ linuxdvb_adapter_create0
|
||||||
if (!conf)
|
if (!conf)
|
||||||
return la;
|
return la;
|
||||||
|
|
||||||
idnode_load(&la->mi_id, conf);
|
idnode_load(&la->ti_id, conf);
|
||||||
if (!htsmsg_get_u32(conf, "number", &u32))
|
if (!htsmsg_get_u32(conf, "number", &u32))
|
||||||
la->la_number = u32;
|
la->la_number = u32;
|
||||||
if ((str = htsmsg_get_str(conf, "rootpath")))
|
if ((str = htsmsg_get_str(conf, "rootpath")))
|
||||||
|
|
|
@ -175,20 +175,20 @@ void linuxdvb_device_save ( linuxdvb_device_t *ld )
|
||||||
|
|
||||||
m = htsmsg_create_map();
|
m = htsmsg_create_map();
|
||||||
|
|
||||||
idnode_save(&ld->mi_id, m);
|
idnode_save(&ld->ti_id, m);
|
||||||
|
|
||||||
/* Adapters */
|
/* Adapters */
|
||||||
l = htsmsg_create_map();
|
l = htsmsg_create_map();
|
||||||
LIST_FOREACH(lh, &ld->lh_children, lh_parent_link) {
|
LIST_FOREACH(lh, &ld->lh_children, lh_parent_link) {
|
||||||
e = htsmsg_create_map();
|
e = htsmsg_create_map();
|
||||||
linuxdvb_adapter_save((linuxdvb_adapter_t*)lh, e);
|
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);
|
htsmsg_add_msg(m, "adapters", l);
|
||||||
|
|
||||||
/* Save */
|
/* Save */
|
||||||
hts_settings_save(m, "input/linuxdvb/devices/%s",
|
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 =
|
const idclass_t linuxdvb_device_class =
|
||||||
|
@ -226,7 +226,7 @@ linuxdvb_device_create0 ( const char *uuid, htsmsg_t *conf )
|
||||||
|
|
||||||
/* Create */
|
/* Create */
|
||||||
ld = calloc(1, sizeof(linuxdvb_device_t));
|
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);
|
free(ld);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -240,7 +240,7 @@ linuxdvb_device_create0 ( const char *uuid, htsmsg_t *conf )
|
||||||
return ld;
|
return ld;
|
||||||
|
|
||||||
/* Load config */
|
/* Load config */
|
||||||
idnode_load(&ld->mi_id, conf);
|
idnode_load(&ld->ti_id, conf);
|
||||||
get_min_dvb_adapter(&ld->ld_devid);
|
get_min_dvb_adapter(&ld->ld_devid);
|
||||||
|
|
||||||
/* Adapters */
|
/* Adapters */
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
/*
|
/*
|
||||||
rk_class
|
|
||||||
* Tvheadend - Linux DVB frontend
|
* Tvheadend - Linux DVB frontend
|
||||||
*
|
*
|
||||||
* Copyright (C) 2013 Adam Sutton
|
* 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
|
static void
|
||||||
linuxdvb_frontend_monitor ( void *aux )
|
linuxdvb_frontend_monitor ( void *aux )
|
||||||
{
|
{
|
||||||
|
uint16_t u16;
|
||||||
|
uint32_t u32;
|
||||||
char buf[256];
|
char buf[256];
|
||||||
linuxdvb_frontend_t *lfe = aux;
|
linuxdvb_frontend_t *lfe = aux;
|
||||||
mpegts_mux_instance_t *mmi = LIST_FIRST(&lfe->mi_mux_active);
|
mpegts_mux_instance_t *mmi = LIST_FIRST(&lfe->mi_mux_active);
|
||||||
|
@ -573,8 +541,15 @@ linuxdvb_frontend_monitor ( void *aux )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Monitor stats */
|
/* Statistics */
|
||||||
linuxdvb_frontend_monitor_stats(lfe, buf);
|
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 *
|
static void *
|
||||||
|
|
|
@ -35,7 +35,7 @@ linuxdvb_hardware_enumerate ( linuxdvb_hardware_list_t *list )
|
||||||
linuxdvb_hardware_t *lh;
|
linuxdvb_hardware_t *lh;
|
||||||
idnode_set_t *set = idnode_set_create();
|
idnode_set_t *set = idnode_set_create();
|
||||||
LIST_FOREACH(lh, list, lh_parent_link)
|
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;
|
return set;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -91,7 +91,7 @@ linuxdvb_satconf_class_frontend_get ( void *o )
|
||||||
static const char *s;
|
static const char *s;
|
||||||
linuxdvb_satconf_t *ls = o;
|
linuxdvb_satconf_t *ls = o;
|
||||||
if (ls->ls_frontend)
|
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
|
else
|
||||||
s = NULL;
|
s = NULL;
|
||||||
return &s;
|
return &s;
|
||||||
|
@ -123,7 +123,7 @@ linuxdvb_satconf_class_frontend_enum (void *o)
|
||||||
for (i = 0; i < is->is_count; i++) {
|
for (i = 0; i < is->is_count; i++) {
|
||||||
mpegts_input_t *mi = (mpegts_input_t*)is->is_array[i];
|
mpegts_input_t *mi = (mpegts_input_t*)is->is_array[i];
|
||||||
htsmsg_t *e = htsmsg_create_map();
|
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;
|
*buf = 0;
|
||||||
mi->mi_display_name(mi, buf, sizeof(buf));
|
mi->mi_display_name(mi, buf, sizeof(buf));
|
||||||
htsmsg_add_str(e, "val", 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;
|
linuxdvb_diseqc_t *ld = (linuxdvb_diseqc_t*)o;
|
||||||
if (ld->ld_satconf)
|
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 =
|
const idclass_t linuxdvb_diseqc_class =
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include "streaming.h"
|
#include "streaming.h"
|
||||||
#include "subscriptions.h"
|
#include "subscriptions.h"
|
||||||
#include "atomic.h"
|
#include "atomic.h"
|
||||||
|
#include "notify.h"
|
||||||
|
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
@ -164,8 +165,15 @@ static void
|
||||||
mpegts_input_started_mux
|
mpegts_input_started_mux
|
||||||
( mpegts_input_t *mi, mpegts_mux_instance_t *mmi )
|
( 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;
|
mmi->mmi_mux->mm_active = mmi;
|
||||||
LIST_INSERT_HEAD(&mi->mi_mux_active, mmi, mmi_active_link);
|
LIST_INSERT_HEAD(&mi->mi_mux_active, mmi, mmi_active_link);
|
||||||
|
notify_reload("input_status");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -177,6 +185,10 @@ mpegts_input_stopped_mux
|
||||||
mmi->mmi_mux->mm_active = NULL;
|
mmi->mmi_mux->mm_active = NULL;
|
||||||
LIST_REMOVE(mmi, mmi_active_link);
|
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));
|
mi->mi_display_name(mi, buf, sizeof(buf));
|
||||||
tvhtrace("mpegts", "%s - flush subscribers", buf);
|
tvhtrace("mpegts", "%s - flush subscribers", buf);
|
||||||
s = LIST_FIRST(&mi->mi_transports);
|
s = LIST_FIRST(&mi->mi_transports);
|
||||||
|
@ -185,6 +197,7 @@ mpegts_input_stopped_mux
|
||||||
service_remove_subscriber(s, NULL, SM_CODE_SUBSCRIPTION_OVERRIDDEN);
|
service_remove_subscriber(s, NULL, SM_CODE_SUBSCRIPTION_OVERRIDDEN);
|
||||||
s = LIST_NEXT(s, s_active_link);
|
s = LIST_NEXT(s, s_active_link);
|
||||||
}
|
}
|
||||||
|
notify_reload("input_status");
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -290,7 +303,7 @@ mpegts_input_recv_packets
|
||||||
pthread_mutex_unlock(&mi->mi_delivery_mutex);
|
pthread_mutex_unlock(&mi->mi_delivery_mutex);
|
||||||
|
|
||||||
/* Bandwidth monitoring */
|
/* Bandwidth monitoring */
|
||||||
atomic_add(&mi->mi_bytes, i);
|
atomic_add(&mmi->mmi_stats.bps, i);
|
||||||
|
|
||||||
/* Reset buffer */
|
/* Reset buffer */
|
||||||
if (len) memmove(tsb, tsb+i, len);
|
if (len) memmove(tsb, tsb+i, len);
|
||||||
|
@ -371,6 +384,59 @@ mpegts_input_flush_mux
|
||||||
pthread_mutex_unlock(&mi->mi_delivery_mutex);
|
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
|
* Creation/Config
|
||||||
* *************************************************************************/
|
* *************************************************************************/
|
||||||
|
@ -383,7 +449,8 @@ mpegts_input_create0
|
||||||
( mpegts_input_t *mi, const idclass_t *class, const char *uuid,
|
( mpegts_input_t *mi, const idclass_t *class, const char *uuid,
|
||||||
htsmsg_t *c )
|
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 */
|
/* Defaults */
|
||||||
mi->mi_is_enabled = mpegts_input_is_enabled;
|
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_started_mux = mpegts_input_started_mux;
|
||||||
mi->mi_stopped_mux = mpegts_input_stopped_mux;
|
mi->mi_stopped_mux = mpegts_input_stopped_mux;
|
||||||
mi->mi_has_subscription = mpegts_input_has_subscription;
|
mi->mi_has_subscription = mpegts_input_has_subscription;
|
||||||
|
mi->ti_get_streams = mpegts_input_get_streams;
|
||||||
|
|
||||||
/* Index */
|
/* Index */
|
||||||
mi->mi_instance = ++mpegts_input_idx;
|
mi->mi_instance = ++mpegts_input_idx;
|
||||||
|
@ -417,7 +485,7 @@ mpegts_input_create0
|
||||||
|
|
||||||
/* Load config */
|
/* Load config */
|
||||||
if (c)
|
if (c)
|
||||||
idnode_load(&mi->mi_id, c);
|
idnode_load(&mi->ti_id, c);
|
||||||
|
|
||||||
return mi;
|
return mi;
|
||||||
}
|
}
|
||||||
|
@ -425,7 +493,7 @@ mpegts_input_create0
|
||||||
void
|
void
|
||||||
mpegts_input_save ( mpegts_input_t *mi, htsmsg_t *m )
|
mpegts_input_save ( mpegts_input_t *mi, htsmsg_t *m )
|
||||||
{
|
{
|
||||||
idnode_save(&mi->mi_id, m);
|
idnode_save(&mi->ti_id, m);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -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({
|
var signal = new Ext.ux.grid.ProgressColumn({
|
||||||
header : "Signal Strength",
|
header : "Signal Strength",
|
||||||
|
@ -149,30 +201,30 @@ tvheadend.status_adapters = function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
function renderBw(value) {
|
function renderBw(value) {
|
||||||
return parseInt(value / 125);
|
return parseInt(value / 1024);
|
||||||
}
|
}
|
||||||
|
|
||||||
var cm = new Ext.grid.ColumnModel([{
|
var cm = new Ext.grid.ColumnModel([{
|
||||||
width : 50,
|
width : 100,
|
||||||
header : "Name",
|
header : "Input",
|
||||||
dataIndex : 'name'
|
dataIndex : 'input'
|
||||||
},{
|
|
||||||
width : 50,
|
|
||||||
header : "Hardware device",
|
|
||||||
dataIndex : 'path'
|
|
||||||
},{
|
},{
|
||||||
width : 100,
|
width : 100,
|
||||||
header : "Currently tuned to",
|
header : "Stream",
|
||||||
dataIndex : 'currentMux'
|
dataIndex : 'stream'
|
||||||
|
},{
|
||||||
|
width : 50,
|
||||||
|
header : "Subs #",
|
||||||
|
dataIndex : 'subs'
|
||||||
|
},{
|
||||||
|
width : 50,
|
||||||
|
header : "Weight",
|
||||||
|
dataIndex : 'weight'
|
||||||
},{
|
},{
|
||||||
width : 100,
|
width : 100,
|
||||||
header : "Bandwidth (kb/s)",
|
header : "Bandwidth (kb/s)",
|
||||||
dataIndex : 'bw',
|
dataIndex : 'bps',
|
||||||
renderer: renderBw
|
renderer: renderBw
|
||||||
},{
|
|
||||||
width : 50,
|
|
||||||
header : "Used for",
|
|
||||||
dataIndex : 'reason'
|
|
||||||
},{
|
},{
|
||||||
width : 50,
|
width : 50,
|
||||||
header : "Bit error rate",
|
header : "Bit error rate",
|
||||||
|
@ -180,7 +232,7 @@ tvheadend.status_adapters = function() {
|
||||||
},{
|
},{
|
||||||
width : 50,
|
width : 50,
|
||||||
header : "Uncorrected bit error rate",
|
header : "Uncorrected bit error rate",
|
||||||
dataIndex : 'uncavg'
|
dataIndex : 'unc'
|
||||||
},{
|
},{
|
||||||
width : 50,
|
width : 50,
|
||||||
header : "SNR",
|
header : "SNR",
|
||||||
|
@ -199,9 +251,9 @@ tvheadend.status_adapters = function() {
|
||||||
loadMask : true,
|
loadMask : true,
|
||||||
stripeRows : true,
|
stripeRows : true,
|
||||||
disableSelection : true,
|
disableSelection : true,
|
||||||
title : 'Adapters',
|
title : 'Stream',
|
||||||
iconCls : 'hardware',
|
iconCls : 'hardware',
|
||||||
store : tvheadend.tvAdapterStore,
|
store : stream_store,
|
||||||
cm : cm,
|
cm : cm,
|
||||||
flex: 1,
|
flex: 1,
|
||||||
viewConfig : {
|
viewConfig : {
|
||||||
|
@ -218,7 +270,7 @@ tvheadend.status = function() {
|
||||||
layout : 'vbox',
|
layout : 'vbox',
|
||||||
title : 'Status',
|
title : 'Status',
|
||||||
iconCls : 'eye',
|
iconCls : 'eye',
|
||||||
items : [ new tvheadend.status_subs, new tvheadend.status_adapters ]
|
items : [ new tvheadend.status_subs, new tvheadend.status_streams ]
|
||||||
});
|
});
|
||||||
|
|
||||||
return panel;
|
return panel;
|
||||||
|
|
Loading…
Add table
Reference in a new issue