]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
stream status: add possibility to clear statistics, introduce tvh_input_instance_t
authorJaroslav Kysela <perex@perex.cz>
Fri, 17 Apr 2015 09:11:00 +0000 (11:11 +0200)
committerJaroslav Kysela <perex@perex.cz>
Fri, 17 Apr 2015 09:11:00 +0000 (11:11 +0200)
src/api/api_status.c
src/input.c
src/input.h
src/input/mpegts.h
src/input/mpegts/linuxdvb/linuxdvb_frontend.c
src/input/mpegts/mpegts_input.c
src/input/mpegts/mpegts_mux.c
src/input/mpegts/satip/satip_frontend.c
src/input/mpegts/tsfile/tsfile_mux.c
src/input/mpegts/tvhdhomerun/tvhdhomerun_frontend.c
src/webui/static/app/status.js

index 0057109fa07bcc0a3ca68882a43d8ecac20269ce..0f7cfef5d05327505ece41f0a946159efe46c94f 100644 (file)
@@ -37,8 +37,10 @@ api_status_inputs
   tvh_input_stream_t *st;
   tvh_input_stream_list_t stl = { 0 };
   
+  pthread_mutex_lock(&global_lock);
   TVH_INPUT_FOREACH(ti)
     ti->ti_get_streams(ti, &stl);
+  pthread_mutex_unlock(&global_lock);
 
   l = htsmsg_create_list();
   while ((st = LIST_FIRST(&stl))) {
@@ -67,11 +69,13 @@ api_status_subscriptions
 
   l = htsmsg_create_list();
   c = 0;
+  pthread_mutex_lock(&global_lock);
   LIST_FOREACH(ths, &subscriptions, ths_global_link) {
     e = subscription_create_msg(ths);
     htsmsg_add_msg(l, NULL, e);
     c++;
   }
+  pthread_mutex_unlock(&global_lock);
 
   *resp = htsmsg_create_map();
   htsmsg_add_msg(*resp, "entries", l);
@@ -120,12 +124,48 @@ api_connections_cancel
   return 0;
 }
 
+static void
+input_clear_stats(const char *uuid)
+{
+  tvh_input_instance_t *tii;
+
+  pthread_mutex_lock(&global_lock);
+  if ((tii = tvh_input_instance_find_by_uuid(uuid)) != NULL)
+    if (tii->tii_clear_stats)
+      tii->tii_clear_stats(tii);
+  pthread_mutex_unlock(&global_lock);
+}
+
+static int
+api_status_input_clear_stats
+  ( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
+{
+  htsmsg_field_t *f;
+  htsmsg_t *ids;
+  const char *uuid;
+
+  if (!(f = htsmsg_field_find(args, "uuid")))
+    return EINVAL;
+  if (!(ids = htsmsg_field_get_list(f))) {
+    if ((uuid = htsmsg_field_get_str(f)) == NULL)
+      return EINVAL;
+    input_clear_stats(uuid);
+  } else {
+    HTSMSG_FOREACH(f, ids) {
+      if ((uuid = htsmsg_field_get_str(f)) == NULL) continue;
+      input_clear_stats(uuid);
+    }
+  }
+  return 0;
+}
+
 void api_status_init ( void )
 {
   static api_hook_t ah[] = {
     { "status/connections",   ACCESS_ADMIN, api_status_connections, NULL },
     { "status/subscriptions", ACCESS_ADMIN, api_status_subscriptions, NULL },
     { "status/inputs",        ACCESS_ADMIN, api_status_inputs, NULL },
+    { "status/inputclrstats", ACCESS_ADMIN, api_status_input_clear_stats, NULL },
     { "connections/cancel",   ACCESS_ADMIN, api_connections_cancel, NULL },
     { NULL },
   };
index cdac24f9eb7d311407ab3c4dcfc5f4845194a7fa..c346dee6f27ee5812c5c608ff9e49a32afd91c4c 100644 (file)
 
 #include "input.h"
 #include "notify.h"
+#include "access.h"
 
 tvh_input_list_t    tvh_inputs;
 tvh_hardware_list_t tvh_hardware;
 
+const idclass_t tvh_input_instance_class =
+{
+  .ic_class      = "tvh_input_instance",
+  .ic_caption    = "Input Instance",
+  .ic_perm_def   = ACCESS_ADMIN
+};
+
 /*
  * Create entry
  */
@@ -59,6 +67,23 @@ tvh_hardware_delete ( tvh_hardware_t *th )
   idnode_unlink(&th->th_id);
 }
 
+/*
+ *
+ */
+
+void
+tvh_input_instance_clear_stats ( tvh_input_instance_t *tii )
+{
+  tvh_input_stream_stats_t *s = &tii->tii_stats;
+
+  atomic_exchange(&s->ber, 0);
+  atomic_exchange(&s->unc, 0);
+  atomic_exchange(&s->cc, 0);
+  atomic_exchange(&s->te, 0);
+  atomic_exchange(&s->ec_block, 0);
+  atomic_exchange(&s->tc_block, 0);
+}
+
 /*
  * Input status handling
  */
index 68254b68d1e3defe1a9b2df0d9fc248d0deac7dd..7b023a1c8c15e8b082b676f8c7c43e20c31db7fb 100644 (file)
@@ -27,6 +27,7 @@
  */
 typedef struct tvh_hardware           tvh_hardware_t;
 typedef struct tvh_input              tvh_input_t;
+typedef struct tvh_input_instance     tvh_input_instance_t;
 typedef struct tvh_input_stream       tvh_input_stream_t;
 typedef struct tvh_input_stream_stats tvh_input_stream_stats_t;
 
@@ -87,6 +88,20 @@ struct tvh_input {
   void (*ti_get_streams) (struct tvh_input *, tvh_input_stream_list_t*);
 };
 
+/*
+ * Generic input instance super-class
+ */
+struct tvh_input_instance {
+  idnode_t tii_id;
+
+  LIST_ENTRY(tvh_input_instance) tii_input_link;
+
+  tvh_input_stream_stats_t tii_stats;
+
+  void (*tii_delete) (tvh_input_instance_t *tii);
+  void (*tii_clear_stats) (tvh_input_instance_t *tii);
+};
+
 /*
  * Generic hardware super-class
  */
@@ -103,6 +118,7 @@ void tvh_hardware_delete ( tvh_hardware_t *th );
  * Class and Global list defs
  */
 extern const idclass_t tvh_input_class;
+extern const idclass_t tvh_input_instance_class;
 
 tvh_input_list_t    tvh_inputs;
 tvh_hardware_list_t tvh_hardware;
@@ -120,6 +136,12 @@ htsmsg_t * tvh_input_stream_create_msg ( tvh_input_stream_t *st );
 
 void tvh_input_stream_destroy ( tvh_input_stream_t *st );
 
+static inline tvh_input_instance_t *
+tvh_input_instance_find_by_uuid(const char *uuid)
+  { return (tvh_input_instance_t*)idnode_find(uuid, &tvh_input_instance_class, NULL); }
+
+void tvh_input_instance_clear_stats ( tvh_input_instance_t *tii );
+
 /*
  * Input subsystem includes
  */
index 66eda6d019ea0549fb7d85865c875cac64ba0e12..58c21b3d33660625e69f755950b321476bdbc04f 100644 (file)
@@ -548,10 +548,9 @@ struct mpegts_service
 /* Physical mux instance */
 struct mpegts_mux_instance
 {
-  idnode_t mmi_id;
+  tvh_input_instance_t;
 
   LIST_ENTRY(mpegts_mux_instance) mmi_mux_link;
-  LIST_ENTRY(mpegts_mux_instance) mmi_input_link;
   LIST_ENTRY(mpegts_mux_instance) mmi_active_link;
 
   streaming_pad_t mmi_streaming_pad;
@@ -559,11 +558,7 @@ struct mpegts_mux_instance
   mpegts_mux_t   *mmi_mux;
   mpegts_input_t *mmi_input;
 
-  tvh_input_stream_stats_t mmi_stats;
-
   int             mmi_tune_failed;
-
-  void (*mmi_delete) (mpegts_mux_instance_t *mmi);
 };
 
 struct mpegts_mux_sub
@@ -598,7 +593,7 @@ struct mpegts_input
 
   mpegts_network_link_list_t mi_networks;
 
-  LIST_HEAD(,mpegts_mux_instance) mi_mux_instances;
+  LIST_HEAD(,tvh_input_instance) mi_mux_instances;
 
 
   /*
@@ -795,7 +790,7 @@ mpegts_service_t *mpegts_mux_find_service(mpegts_mux_t *ms, uint16_t sid);
                                             &type##_class, uuid,\
                                             mi, mm);
 
-void mpegts_mux_instance_delete ( mpegts_mux_instance_t *mmi );
+void mpegts_mux_instance_delete ( tvh_input_instance_t *tii );
 
 int mpegts_mux_instance_start
   ( mpegts_mux_instance_t **mmiptr );
index 59fc77d9c211d4df29eeec8b730eb6e5d0cd232b..8daedbbffa8b5a8938eb39295f586ed0844fb211 100644 (file)
@@ -662,18 +662,18 @@ linuxdvb_frontend_monitor ( void *aux )
     gotprop = 0;
     if(ioctl_check(lfe, 1) && fe_properties[0].u.st.len > 0) {
       if(fe_properties[0].u.st.stat[0].scale == FE_SCALE_RELATIVE) {
-        mmi->mmi_stats.signal_scale = SIGNAL_STATUS_SCALE_RELATIVE;
-        mmi->mmi_stats.signal = fe_properties[0].u.st.stat[0].uvalue;
+        mmi->tii_stats.signal_scale = SIGNAL_STATUS_SCALE_RELATIVE;
+        mmi->tii_stats.signal = fe_properties[0].u.st.stat[0].uvalue;
         gotprop = 1;
       }
       else if(fe_properties[0].u.st.stat[0].scale == FE_SCALE_DECIBEL) {
-        mmi->mmi_stats.signal_scale = SIGNAL_STATUS_SCALE_DECIBEL;
-        mmi->mmi_stats.signal = fe_properties[0].u.st.stat[0].svalue;
+        mmi->tii_stats.signal_scale = SIGNAL_STATUS_SCALE_DECIBEL;
+        mmi->tii_stats.signal = fe_properties[0].u.st.stat[0].svalue;
         gotprop = 1;
       }
       else {
         ioctl_bad(lfe, 1);
-        mmi->mmi_stats.signal_scale = SIGNAL_STATUS_SCALE_UNKNOWN;
+        mmi->tii_stats.signal_scale = SIGNAL_STATUS_SCALE_UNKNOWN;
         if (logit)
           tvhlog(LOG_WARNING, "linuxdvb", "Unhandled signal scale: %d",
                  fe_properties[0].u.st.stat[0].scale);
@@ -682,12 +682,12 @@ linuxdvb_frontend_monitor ( void *aux )
     if(!gotprop && ioctl_check(lfe, 2)) {
       /* try old API */
       if (!ioctl(lfe->lfe_fe_fd, FE_READ_SIGNAL_STRENGTH, &u16)) {
-        mmi->mmi_stats.signal_scale = SIGNAL_STATUS_SCALE_RELATIVE;
-        mmi->mmi_stats.signal = u16;
+        mmi->tii_stats.signal_scale = SIGNAL_STATUS_SCALE_RELATIVE;
+        mmi->tii_stats.signal = u16;
       }
       else {
         ioctl_bad(lfe, 2);
-        mmi->mmi_stats.signal_scale = SIGNAL_STATUS_SCALE_UNKNOWN;
+        mmi->tii_stats.signal_scale = SIGNAL_STATUS_SCALE_UNKNOWN;
         if (logit)
           tvhlog(LOG_WARNING, "linuxdvb", "Unable to provide signal strength value.");
       }
@@ -697,7 +697,7 @@ linuxdvb_frontend_monitor ( void *aux )
     gotprop = 0;
     if(ioctl_check(lfe, 3) && fe_properties[1].u.st.len > 0) {
       if(fe_properties[1].u.st.stat[0].scale == FE_SCALE_COUNTER) {
-        mmi->mmi_stats.ec_bit = fe_properties[1].u.st.stat[0].uvalue;
+        mmi->tii_stats.ec_bit = fe_properties[1].u.st.stat[0].uvalue;
         gotprop = 1;
       }
       else {
@@ -711,12 +711,12 @@ linuxdvb_frontend_monitor ( void *aux )
     if(gotprop && (fe_properties[2].u.st.len > 0)) {
       gotprop = 0;
       if(ioctl_check(lfe, 4) && fe_properties[2].u.st.stat[0].scale == FE_SCALE_COUNTER) {
-        mmi->mmi_stats.tc_bit = fe_properties[2].u.st.stat[0].uvalue;
+        mmi->tii_stats.tc_bit = fe_properties[2].u.st.stat[0].uvalue;
         gotprop = 1;
       }
       else {
         ioctl_bad(lfe, 4);
-        mmi->mmi_stats.ec_bit = 0; /* both values or none */
+        mmi->tii_stats.ec_bit = 0; /* both values or none */
         if (logit)
           tvhlog(LOG_WARNING, "linuxdvb", "Unhandled TOTAL_BIT_COUNT scale: %d",
                  fe_properties[2].u.st.stat[0].scale);
@@ -725,7 +725,7 @@ linuxdvb_frontend_monitor ( void *aux )
     if(!gotprop && ioctl_check(lfe, 5)) {
       /* try old API */
       if (!ioctl(lfe->lfe_fe_fd, FE_READ_BER, &u32))
-        mmi->mmi_stats.ber = u32;
+        mmi->tii_stats.ber = u32;
       else {
         ioctl_bad(lfe, 5);
         if (logit)
@@ -737,18 +737,18 @@ linuxdvb_frontend_monitor ( void *aux )
     gotprop = 0;
     if(ioctl_check(lfe, 6) && fe_properties[3].u.st.len > 0) {
       if(fe_properties[3].u.st.stat[0].scale == FE_SCALE_RELATIVE) {
-        mmi->mmi_stats.snr_scale = SIGNAL_STATUS_SCALE_RELATIVE;
-        mmi->mmi_stats.snr = fe_properties[3].u.st.stat[0].uvalue;
+        mmi->tii_stats.snr_scale = SIGNAL_STATUS_SCALE_RELATIVE;
+        mmi->tii_stats.snr = fe_properties[3].u.st.stat[0].uvalue;
         gotprop = 1;
       }
       else if(fe_properties[3].u.st.stat[0].scale == FE_SCALE_DECIBEL) {
-        mmi->mmi_stats.snr_scale = SIGNAL_STATUS_SCALE_DECIBEL;
-        mmi->mmi_stats.snr = fe_properties[3].u.st.stat[0].svalue;
+        mmi->tii_stats.snr_scale = SIGNAL_STATUS_SCALE_DECIBEL;
+        mmi->tii_stats.snr = fe_properties[3].u.st.stat[0].svalue;
         gotprop = 1;
       }
       else {
         ioctl_bad(lfe, 6);
-        mmi->mmi_stats.snr_scale = SIGNAL_STATUS_SCALE_UNKNOWN;
+        mmi->tii_stats.snr_scale = SIGNAL_STATUS_SCALE_UNKNOWN;
         if (logit)
           tvhlog(LOG_WARNING, "linuxdvb", "Unhandled SNR scale: %d",
                  fe_properties[3].u.st.stat[0].scale);
@@ -757,12 +757,12 @@ linuxdvb_frontend_monitor ( void *aux )
     if(!gotprop && ioctl_check(lfe, 7)) {
       /* try old API */
       if (!ioctl(lfe->lfe_fe_fd, FE_READ_SNR, &u16)) {
-        mmi->mmi_stats.snr_scale = SIGNAL_STATUS_SCALE_RELATIVE;
-        mmi->mmi_stats.snr = u16;
+        mmi->tii_stats.snr_scale = SIGNAL_STATUS_SCALE_RELATIVE;
+        mmi->tii_stats.snr = u16;
       }
       else {
         ioctl_bad(lfe, 7);
-        mmi->mmi_stats.snr_scale = SIGNAL_STATUS_SCALE_UNKNOWN;
+        mmi->tii_stats.snr_scale = SIGNAL_STATUS_SCALE_UNKNOWN;
         if (logit)
           tvhlog(LOG_WARNING, "linuxdvb", "Unable to provide SNR value.");
       }
@@ -772,7 +772,7 @@ linuxdvb_frontend_monitor ( void *aux )
     gotprop = 0;
     if(ioctl_check(lfe, 8) && fe_properties[4].u.st.len > 0) {
       if(fe_properties[4].u.st.stat[0].scale == FE_SCALE_COUNTER) {
-        mmi->mmi_stats.unc = mmi->mmi_stats.ec_block = fe_properties[4].u.st.stat[0].uvalue;
+        mmi->tii_stats.unc = mmi->tii_stats.ec_block = fe_properties[4].u.st.stat[0].uvalue;
         gotprop = 1;
       }
       else {
@@ -787,12 +787,12 @@ linuxdvb_frontend_monitor ( void *aux )
     if(gotprop && (fe_properties[5].u.st.len > 0)) {
       gotprop = 0;
       if(ioctl_check(lfe, 9) && fe_properties[5].u.st.stat[0].scale == FE_SCALE_COUNTER) {
-        mmi->mmi_stats.tc_block = fe_properties[5].u.st.stat[0].uvalue;
+        mmi->tii_stats.tc_block = fe_properties[5].u.st.stat[0].uvalue;
         gotprop = 1;
       }
       else {
         ioctl_bad(lfe, 9);
-        mmi->mmi_stats.ec_block = mmi->mmi_stats.unc = 0; /* both values or none */
+        mmi->tii_stats.ec_block = mmi->tii_stats.unc = 0; /* both values or none */
         if (logit)
           tvhlog(LOG_WARNING, "linuxdvb", "Unhandled TOTAL_BLOCK_COUNT scale: %d",
                  fe_properties[5].u.st.stat[0].scale);
@@ -801,7 +801,7 @@ linuxdvb_frontend_monitor ( void *aux )
     if(!gotprop && ioctl_check(lfe, 10)) {
       /* try old API */
       if (!ioctl(lfe->lfe_fe_fd, FE_READ_UNCORRECTED_BLOCKS, &u32)) {
-        mmi->mmi_stats.unc = u32;
+        mmi->tii_stats.unc = u32;
         gotprop = 1;
       }
       else {
@@ -816,34 +816,34 @@ linuxdvb_frontend_monitor ( void *aux )
   {
     ioctl_bad(lfe, 0);
     if (ioctl_check(lfe, 1) && !ioctl(lfe->lfe_fe_fd, FE_READ_SIGNAL_STRENGTH, &u16)) {
-      mmi->mmi_stats.signal_scale = SIGNAL_STATUS_SCALE_RELATIVE;
-      mmi->mmi_stats.signal = u16;
+      mmi->tii_stats.signal_scale = SIGNAL_STATUS_SCALE_RELATIVE;
+      mmi->tii_stats.signal = u16;
     }
     else {
       ioctl_bad(lfe, 1);
-      mmi->mmi_stats.signal_scale = SIGNAL_STATUS_SCALE_UNKNOWN;
+      mmi->tii_stats.signal_scale = SIGNAL_STATUS_SCALE_UNKNOWN;
       if (logit)
         tvhlog(LOG_WARNING, "linuxdvb", "Unable to provide signal strength value.");
     }
     if (ioctl_check(lfe, 2) && !ioctl(lfe->lfe_fe_fd, FE_READ_BER, &u32))
-      mmi->mmi_stats.ber = u32;
+      mmi->tii_stats.ber = u32;
     else {
       ioctl_bad(lfe, 2);
       if (logit)
         tvhlog(LOG_WARNING, "linuxdvb", "Unable to provide BER value.");
     }
     if (ioctl_check(lfe, 3) && !ioctl(lfe->lfe_fe_fd, FE_READ_SNR, &u16)) {
-      mmi->mmi_stats.snr_scale = SIGNAL_STATUS_SCALE_RELATIVE;
-      mmi->mmi_stats.snr = u16;
+      mmi->tii_stats.snr_scale = SIGNAL_STATUS_SCALE_RELATIVE;
+      mmi->tii_stats.snr = u16;
     }
     else {
       ioctl_bad(lfe, 3);
-      mmi->mmi_stats.snr_scale = SIGNAL_STATUS_SCALE_UNKNOWN;
+      mmi->tii_stats.snr_scale = SIGNAL_STATUS_SCALE_UNKNOWN;
       if (logit)
         tvhlog(LOG_WARNING, "linuxdvb", "Unable to provide SNR value.");
     }
     if (ioctl_check(lfe, 4) && !ioctl(lfe->lfe_fe_fd, FE_READ_UNCORRECTED_BLOCKS, &u32))
-      mmi->mmi_stats.unc = u32;
+      mmi->tii_stats.unc = u32;
     else {
       ioctl_bad(lfe, 4);
       if (logit)
@@ -853,16 +853,16 @@ linuxdvb_frontend_monitor ( void *aux )
 
   /* Send message */
   sigstat.status_text  = signal2str(status);
-  sigstat.snr          = mmi->mmi_stats.snr;
-  sigstat.signal       = mmi->mmi_stats.signal;
-  sigstat.ber          = mmi->mmi_stats.ber;
-  sigstat.unc          = mmi->mmi_stats.unc;
-  sigstat.signal_scale = mmi->mmi_stats.signal_scale;
-  sigstat.snr_scale    = mmi->mmi_stats.snr_scale;
-  sigstat.ec_bit       = mmi->mmi_stats.ec_bit;
-  sigstat.tc_bit       = mmi->mmi_stats.tc_bit;
-  sigstat.ec_block     = mmi->mmi_stats.ec_block;
-  sigstat.tc_block     = mmi->mmi_stats.tc_block;
+  sigstat.snr          = mmi->tii_stats.snr;
+  sigstat.signal       = mmi->tii_stats.signal;
+  sigstat.ber          = mmi->tii_stats.ber;
+  sigstat.unc          = mmi->tii_stats.unc;
+  sigstat.signal_scale = mmi->tii_stats.signal_scale;
+  sigstat.snr_scale    = mmi->tii_stats.snr_scale;
+  sigstat.ec_bit       = mmi->tii_stats.ec_bit;
+  sigstat.tc_bit       = mmi->tii_stats.tc_bit;
+  sigstat.ec_block     = mmi->tii_stats.ec_block;
+  sigstat.tc_block     = mmi->tii_stats.tc_block;
   sm.sm_type = SMT_SIGNAL_STATUS;
   sm.sm_data = &sigstat;
   LIST_FOREACH(s, &lfe->mi_transports, s_active_link) {
index a3b0ad06f05320046f6bad8ae8b89a6ea91fa664..f27fdfe32c835438ed7d17ebcb10e9c7a8e92775 100644 (file)
@@ -673,10 +673,10 @@ mpegts_input_create_mux_instance
   ( mpegts_input_t *mi, mpegts_mux_t *mm )
 {
   extern const idclass_t mpegts_mux_instance_class;
-  mpegts_mux_instance_t *mmi;
-  LIST_FOREACH(mmi, &mi->mi_mux_instances, mmi_input_link)
-    if (mmi->mmi_mux == mm) break;
-  if (!mmi)
+  tvh_input_instance_t *tii;
+  LIST_FOREACH(tii, &mi->mi_mux_instances, tii_input_link)
+    if (((mpegts_mux_instance_t *)tii)->mmi_mux == mm) break;
+  if (!tii)
     (void)mpegts_mux_instance_create(mpegts_mux_instance, NULL, mi, mm);
 }
 
@@ -871,7 +871,7 @@ mpegts_input_recv_packets
   /* Check for sync */
   while ( (len >= MIN_TS_SYN) &&
           ((len2 = ts_sync_count(tsb, len)) < MIN_TS_SYN) ) {
-    mmi->mmi_stats.unc++;
+    mmi->tii_stats.unc++;
     --len;
     ++tsb;
     ++off;
@@ -1079,7 +1079,7 @@ mpegts_input_process
     /* Transport error */
     if (pid & 0x8000) {
       if ((pid & 0x1FFF) != 0x1FFF)
-        ++mmi->mmi_stats.te;
+        ++mmi->tii_stats.te;
     }
     
     pid &= 0x1FFF;
@@ -1102,7 +1102,7 @@ mpegts_input_process
           cc = tsb2[3] & 0x0f;
           if (cc2 != 0xff && cc2 != cc) {
             tvhtrace("mpegts", "pid %04X cc err %2d != %2d", pid, cc, cc2);
-          ++mmi->mmi_stats.cc;
+            ++mmi->tii_stats.cc;
           }
           cc2 = (cc + 1) & 0xF;
         }
@@ -1214,7 +1214,7 @@ done:
     pthread_cond_signal(&mi->mi_table_cond);
 
   /* Bandwidth monitoring */
-  atomic_add(&mmi->mmi_stats.bps, tsb - mpkt->mp_data);
+  atomic_add(&mmi->tii_stats.bps, tsb - mpkt->mp_data);
 }
 
 static void *
@@ -1352,15 +1352,15 @@ mpegts_input_stream_status
         w = MAX(w, ths->ths_weight);
       }
 
-  st->uuid        = strdup(idnode_uuid_as_str(&mmi->mmi_id));
+  st->uuid        = strdup(idnode_uuid_as_str(&mmi->tii_id));
   mi->mi_display_name(mi, buf, sizeof(buf));
   st->input_name  = strdup(buf);
   mpegts_mux_nice_name(mm, buf, sizeof(buf));
   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;
+  st->stats       = mmi->tii_stats;
+  st->stats.bps   = atomic_exchange(&mmi->tii_stats.bps, 0) * 8;
 }
 
 static void
@@ -1524,19 +1524,19 @@ void
 mpegts_input_delete ( mpegts_input_t *mi, int delconf )
 {
   mpegts_network_link_t *mnl;
-  mpegts_mux_instance_t *mmi, *mmi_next;
+  tvh_input_instance_t *tii, *tii_next;
 
   /* Remove networks */
   while ((mnl = LIST_FIRST(&mi->mi_networks)))
     mpegts_input_del_network(mnl);
 
   /* Remove mux instances assigned to this input */
-  mmi = LIST_FIRST(&mi->mi_mux_instances);
-  while (mmi) {
-    mmi_next = LIST_NEXT(mmi, mmi_input_link);
-    if (mmi->mmi_input == mi)
-      mmi->mmi_delete(mmi);
-    mmi = mmi_next;
+  tii = LIST_FIRST(&mi->mi_mux_instances);
+  while (tii) {
+    tii_next = LIST_NEXT(tii, tii_input_link);
+    if (((mpegts_mux_instance_t *)tii)->mmi_input == mi)
+      tii->tii_delete(tii);
+    tii = tii_next;
   }
 
   /* Remove global refs */
index 9a007ac6e0687ccb214cd29b85b27ec236973be7..1f9c6670c9e7ef32251b7ca71d8de769fd09fa20 100644 (file)
@@ -37,6 +37,7 @@ static void mpegts_mux_scan_timeout ( void *p );
 
 const idclass_t mpegts_mux_instance_class =
 {
+  .ic_super      = &tvh_input_instance_class,
   .ic_class      = "mpegts_mux_instance",
   .ic_caption    = "MPEGTS Multiplex Phy",
   .ic_perm_def   = ACCESS_ADMIN
@@ -44,11 +45,13 @@ const idclass_t mpegts_mux_instance_class =
 
 void
 mpegts_mux_instance_delete
-  ( mpegts_mux_instance_t *mmi )
+  ( tvh_input_instance_t *tii )
 {
-  idnode_unlink(&mmi->mmi_id);
+  mpegts_mux_instance_t *mmi = (mpegts_mux_instance_t *)tii;
+
+  idnode_unlink(&tii->tii_id);
   LIST_REMOVE(mmi, mmi_mux_link);
-  LIST_REMOVE(mmi, mmi_input_link);
+  LIST_REMOVE(tii, tii_input_link);
   free(mmi);
 }
 
@@ -58,7 +61,7 @@ mpegts_mux_instance_create0
     mpegts_input_t *mi, mpegts_mux_t *mm )
 {
   // TODO: does this need to be an idnode?
-  if (idnode_insert(&mmi->mmi_id, uuid, class, 0)) {
+  if (idnode_insert(&mmi->tii_id, uuid, class, 0)) {
     free(mmi);
     return NULL;
   }
@@ -68,10 +71,11 @@ mpegts_mux_instance_create0
   mmi->mmi_input = mi;
   
   /* Callbacks */
-  mmi->mmi_delete = mpegts_mux_instance_delete;
+  mmi->tii_delete = mpegts_mux_instance_delete;
+  mmi->tii_clear_stats = tvh_input_instance_clear_stats;
 
   LIST_INSERT_HEAD(&mm->mm_instances, mmi, mmi_mux_link);
-  LIST_INSERT_HEAD(&mi->mi_mux_instances, mmi, mmi_input_link);
+  LIST_INSERT_HEAD(&mi->mi_mux_instances, (tvh_input_instance_t *)mmi, tii_input_link);
 
 
   return mmi;
@@ -621,7 +625,7 @@ mpegts_mux_delete ( mpegts_mux_t *mm, int delconf )
 
   /* Remove instances */
   while ((mmi = LIST_FIRST(&mm->mm_instances))) {
-    mmi->mmi_delete(mmi);
+    mmi->tii_delete((tvh_input_instance_t *)mmi);
   }
 
   /* Remove raw subscribers */
index 23b7a2ed8443b2d3bdb8fcb6d7af3f353196a772..f80590c2d0179346a4d703b1ae908dc492c923ec 100644 (file)
@@ -76,16 +76,16 @@ satip_frontend_signal_cb( void *aux )
     lfe->sf_tables = 1;
   }
   sigstat.status_text  = signal2str(lfe->sf_status);
-  sigstat.snr          = mmi->mmi_stats.snr;
-  sigstat.signal       = mmi->mmi_stats.signal;
-  sigstat.ber          = mmi->mmi_stats.ber;
-  sigstat.unc          = mmi->mmi_stats.unc;
-  sigstat.signal_scale = mmi->mmi_stats.signal_scale;
-  sigstat.snr_scale    = mmi->mmi_stats.snr_scale;
-  sigstat.ec_bit       = mmi->mmi_stats.ec_bit;
-  sigstat.tc_bit       = mmi->mmi_stats.tc_bit;
-  sigstat.ec_block     = mmi->mmi_stats.ec_block;
-  sigstat.tc_block     = mmi->mmi_stats.tc_block;
+  sigstat.snr          = mmi->tii_stats.snr;
+  sigstat.signal       = mmi->tii_stats.signal;
+  sigstat.ber          = mmi->tii_stats.ber;
+  sigstat.unc          = mmi->tii_stats.unc;
+  sigstat.signal_scale = mmi->tii_stats.signal_scale;
+  sigstat.snr_scale    = mmi->tii_stats.snr_scale;
+  sigstat.ec_bit       = mmi->tii_stats.ec_bit;
+  sigstat.tc_bit       = mmi->tii_stats.tc_bit;
+  sigstat.ec_block     = mmi->tii_stats.ec_block;
+  sigstat.tc_block     = mmi->tii_stats.tc_block;
   sm.sm_type = SMT_SIGNAL_STATUS;
   sm.sm_data = &sigstat;
   LIST_FOREACH(svc, &lfe->mi_transports, s_active_link) {
@@ -722,20 +722,20 @@ satip_frontend_decode_rtcp( satip_frontend_t *lfe, const char *name,
             return;
           if (atoi(argv[0]) != lfe->sf_number)
             return;
-          mmi->mmi_stats.signal =
+          mmi->tii_stats.signal =
             atoi(argv[1]) * 0xffff / lfe->sf_device->sd_sig_scale;
-          mmi->mmi_stats.signal_scale =
+          mmi->tii_stats.signal_scale =
             SIGNAL_STATUS_SCALE_RELATIVE;
           if (atoi(argv[2]) > 0)
             status = SIGNAL_GOOD;
-          mmi->mmi_stats.snr = atoi(argv[3]) * 0xffff / 15;
-          mmi->mmi_stats.snr_scale =
+          mmi->tii_stats.snr = atoi(argv[3]) * 0xffff / 15;
+          mmi->tii_stats.snr_scale =
             SIGNAL_STATUS_SCALE_RELATIVE;
           if (status == SIGNAL_GOOD &&
-              mmi->mmi_stats.signal == 0 && mmi->mmi_stats.snr == 0) {
+              mmi->tii_stats.signal == 0 && mmi->tii_stats.snr == 0) {
             /* some values that we're tuned */
-            mmi->mmi_stats.signal = 50 * 0xffff / 100;
-            mmi->mmi_stats.snr = 12 * 0xffff / 15;
+            mmi->tii_stats.signal = 50 * 0xffff / 100;
+            mmi->tii_stats.snr = 12 * 0xffff / 15;
           }
           goto ok;          
         } else if (strncmp(s, "ver=1.0;", 8) == 0) {
@@ -747,14 +747,14 @@ satip_frontend_decode_rtcp( satip_frontend_t *lfe, const char *name,
             return;
           if (atoi(argv[0]) != lfe->sf_number)
             return;
-          mmi->mmi_stats.signal =
+          mmi->tii_stats.signal =
             atoi(argv[1]) * 0xffff / lfe->sf_device->sd_sig_scale;
-          mmi->mmi_stats.signal_scale =
+          mmi->tii_stats.signal_scale =
             SIGNAL_STATUS_SCALE_RELATIVE;
           if (atoi(argv[2]) > 0)
             status = SIGNAL_GOOD;
-          mmi->mmi_stats.snr = atoi(argv[3]) * 0xffff / 15;
-          mmi->mmi_stats.snr_scale =
+          mmi->tii_stats.snr = atoi(argv[3]) * 0xffff / 15;
+          mmi->tii_stats.snr_scale =
             SIGNAL_STATUS_SCALE_RELATIVE;
           goto ok;          
         } else if (strncmp(s, "ver=1.1;tuner=", 14) == 0) {
@@ -763,14 +763,14 @@ satip_frontend_decode_rtcp( satip_frontend_t *lfe, const char *name,
             return;
           if (atoi(argv[0]) != lfe->sf_number)
             return;
-          mmi->mmi_stats.signal =
+          mmi->tii_stats.signal =
             atoi(argv[1]) * 0xffff / lfe->sf_device->sd_sig_scale;
-          mmi->mmi_stats.signal_scale =
+          mmi->tii_stats.signal_scale =
             SIGNAL_STATUS_SCALE_RELATIVE;
           if (atoi(argv[2]) > 0)
             status = SIGNAL_GOOD;
-          mmi->mmi_stats.snr = atoi(argv[3]) * 0xffff / 15;
-          mmi->mmi_stats.snr_scale =
+          mmi->tii_stats.snr = atoi(argv[3]) * 0xffff / 15;
+          mmi->tii_stats.snr_scale =
             SIGNAL_STATUS_SCALE_RELATIVE;
           goto ok;
         }
@@ -782,9 +782,9 @@ satip_frontend_decode_rtcp( satip_frontend_t *lfe, const char *name,
   return;
 
 ok:
-  if (mmi->mmi_stats.snr < 2 && status == SIGNAL_GOOD)
+  if (mmi->tii_stats.snr < 2 && status == SIGNAL_GOOD)
     status              = SIGNAL_BAD;
-  else if (mmi->mmi_stats.snr < 4 && status == SIGNAL_GOOD)
+  else if (mmi->tii_stats.snr < 4 && status == SIGNAL_GOOD)
     status              = SIGNAL_FAINT;
   lfe->sf_status        = status;
 }
@@ -1503,7 +1503,7 @@ new_tune:
     }
     pthread_mutex_lock(&lfe->sf_dvr_lock);
     if (lfe->sf_req == lfe->sf_req_thread) {
-      mmi->mmi_stats.unc += unc;
+      mmi->tii_stats.unc += unc;
       mpegts_input_recv_packets((mpegts_input_t*)lfe, mmi,
                                 &sb, NULL, NULL);
     } else
index b5333fe46f84506e942783a1ade06fa4bf0900d1..a3fedbbe09bdb839053c8284d851fb400253f4b2 100644 (file)
@@ -23,12 +23,12 @@ extern const idclass_t mpegts_mux_class;
 extern const idclass_t mpegts_mux_instance_class;
 
 static void
-tsfile_mux_instance_delete( mpegts_mux_instance_t *_mmi )
+tsfile_mux_instance_delete( tvh_input_instance_t *tii )
 {
-  tsfile_mux_instance_t *mmi = (tsfile_mux_instance_t *)_mmi;
+  tsfile_mux_instance_t *mmi = (tsfile_mux_instance_t *)tii;
 
   free(mmi->mmi_tsfile_path);
-  mpegts_mux_instance_delete(_mmi);
+  mpegts_mux_instance_delete(tii);
 }
 
 tsfile_mux_instance_t *
@@ -41,7 +41,7 @@ tsfile_mux_instance_create
 #undef tsfile_mux_instance_class
   mmi->mmi_tsfile_path    = strdup(path);
   mmi->mmi_tsfile_pcr_pid = MPEGTS_PID_NONE;
-  mmi->mmi_delete         = tsfile_mux_instance_delete;
+  mmi->tii_delete         = tsfile_mux_instance_delete;
   tvhtrace("tsfile", "mmi created %p path %s", mmi, mmi->mmi_tsfile_path);
   return mmi;
 }
index b8bd705aeac0ae06a3669824a381cf5bb2e32e93..5e277cb1722859e12a64d58bb968a2f6dc8e6985 100644 (file)
@@ -300,19 +300,19 @@ tvhdhomerun_frontend_monitor_cb( void *aux )
 
   if(tuner_status.signal_present) {
     /* TODO: totaly stupid conversion from 0-100 scale to 0-655.35 */
-    mmi->mmi_stats.snr = tuner_status.signal_to_noise_quality * 655.35;
-    mmi->mmi_stats.signal = tuner_status.signal_strength * 655.35;
+    mmi->tii_stats.snr = tuner_status.signal_to_noise_quality * 655.35;
+    mmi->tii_stats.signal = tuner_status.signal_strength * 655.35;
   } else {
-    mmi->mmi_stats.snr = 0;
+    mmi->tii_stats.snr = 0;
   }
 
   sigstat.status_text  = signal2str(hfe->hf_status);
-  sigstat.snr          = mmi->mmi_stats.snr;
-  sigstat.snr_scale    = mmi->mmi_stats.snr_scale = SIGNAL_STATUS_SCALE_RELATIVE;
-  sigstat.signal       = mmi->mmi_stats.signal;
-  sigstat.signal_scale = mmi->mmi_stats.signal_scale = SIGNAL_STATUS_SCALE_RELATIVE;
-  sigstat.ber          = mmi->mmi_stats.ber;
-  sigstat.unc          = mmi->mmi_stats.unc;
+  sigstat.snr          = mmi->tii_stats.snr;
+  sigstat.snr_scale    = mmi->tii_stats.snr_scale = SIGNAL_STATUS_SCALE_RELATIVE;
+  sigstat.signal       = mmi->tii_stats.signal;
+  sigstat.signal_scale = mmi->tii_stats.signal_scale = SIGNAL_STATUS_SCALE_RELATIVE;
+  sigstat.ber          = mmi->tii_stats.ber;
+  sigstat.unc          = mmi->tii_stats.unc;
   sm.sm_type = SMT_SIGNAL_STATUS;
   sm.sm_data = &sigstat;
 
index 819032f8d11d5576dd8533f0f6a8db5dbfde8cc3..356cb3373a3a989675b23477b4d18ce1d778a8a5 100644 (file)
@@ -231,6 +231,33 @@ tvheadend.status_streams = function(panel, index)
         if (grid)
             return;
 
+        var actions = new Ext.ux.grid.RowActions({
+            header: '',
+            width: 10,
+            actions: [
+                {
+                    iconCls: 'undo',
+                    qtip: 'Clear statistics',
+                    cb: function(grid, rec, act, row) {
+                        var uuid = grid.getStore().getAt(row).data.uuid;
+                        Ext.MessageBox.confirm('Clear statistics',
+                            'Clear statistics for selected input?',
+                            function(button) {
+                                if (button === 'no')
+                                    return;
+                                Ext.Ajax.request({
+                                    url: 'api/status/inputclrstats',
+                                    params: { uuid: uuid }
+                                });
+                            }
+                       );
+                   }
+               },
+            ],
+            destroy: function() {
+            }
+        });
+
         store = new Ext.data.JsonStore({
             root: 'entries',
             totalProperty: 'totalCount',
@@ -288,6 +315,7 @@ tvheadend.status_streams = function(panel, index)
         }
 
         var cm = new Ext.grid.ColumnModel([
+            actions,
             {
                 width: 120,
                 header: "Input",
@@ -402,7 +430,8 @@ tvheadend.status_streams = function(panel, index)
             flex: 1,
             viewConfig: {
                 forceFit: true
-            }
+            },
+            plugins: [actions]
         });
         
         dpanel.add(grid);