Index: trunk/BNC/bnc.pro
===================================================================
--- trunk/BNC/bnc.pro	(revision 1971)
+++ trunk/BNC/bnc.pro	(revision 1972)
@@ -38,4 +38,5 @@
           bncnetqueryudp0.h bncudpport.h                              \ 
           bncserialport.h bncnetquerys.h bncfigure.h                  \ 
+          bncfigurelate.h                                             \ 
           RTCM/GPSDecoder.h RTCM/RTCM2.h RTCM/RTCM2Decoder.h          \
           RTCM/RTCM2_2021.h RTCM/rtcm_utils.h                         \
@@ -60,4 +61,5 @@
           bncnetqueryudp0.cpp bncudpport.cpp                          \
           bncserialport.cpp bncnetquerys.cpp bncfigure.cpp            \
+          bncfigurelate.cpp                                           \
           RTCM/RTCM2.cpp RTCM/RTCM2Decoder.cpp                        \
           RTCM/RTCM2_2021.cpp RTCM/rtcm_utils.cpp                     \
Index: trunk/BNC/bncfigurelate.cpp
===================================================================
--- trunk/BNC/bncfigurelate.cpp	(revision 1972)
+++ trunk/BNC/bncfigurelate.cpp	(revision 1972)
@@ -0,0 +1,193 @@
+// Part of BNC, a utility for retrieving decoding and
+// converting GNSS data streams from NTRIP broadcasters.
+//
+// Copyright (C) 2007
+// German Federal Agency for Cartography and Geodesy (BKG)
+// http://www.bkg.bund.de
+// Czech Technical University Prague, Department of Geodesy
+// http://www.fsv.cvut.cz
+//
+// Email: euref-ip@bkg.bund.de
+//
+// 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, version 2.
+//
+// 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, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+/* -------------------------------------------------------------------------
+ * BKG NTRIP Client
+ * -------------------------------------------------------------------------
+ *
+ * Class:      bncFigureLate
+ *
+ * Purpose:    
+ *
+ * Author:     Perlt, Mervart
+ *
+ * Created:    11-Nov-2009
+ *
+ * Changes:    
+ *
+ * -----------------------------------------------------------------------*/
+
+#include <iostream>
+
+#include "bncfigurelate.h" 
+#include "bncsettings.h"
+
+using namespace std;
+
+// Constructor
+////////////////////////////////////////////////////////////////////////////
+bncFigureLate::bncFigureLate(QWidget *parent) : QWidget(parent) {
+  updateMountPoints();
+  slotNextAnimationFrame();
+  for (int ii = 0; ii <= 1000; ii++) {
+    _rgb[0][ii] = qrand() % 255;
+    _rgb[2][ii] = qrand() % 255;
+    _rgb[1][ii] = qrand() % 255;
+  }
+}
+
+// Destructor
+////////////////////////////////////////////////////////////////////////////
+bncFigureLate::~bncFigureLate() { 
+}
+
+// 
+////////////////////////////////////////////////////////////////////////////
+void bncFigureLate::updateMountPoints() {
+  QMutexLocker locker(&_mutex);
+
+  _counter = 0;
+  _maxLate = 0;
+
+  QMapIterator<QByteArray, sumAndMean*> it1(_bytes);
+  while (it1.hasNext()) {
+    it1.next();
+    delete it1.value();
+  }
+  _bytes.clear();
+
+  bncSettings settings;
+  QListIterator<QString> it(settings.value("mountPoints").toStringList());
+  while (it.hasNext()) {
+    QStringList hlp   = it.next().split(" ");
+    QUrl        url(hlp[0]);
+    QByteArray  staID = url.path().mid(1).toAscii();
+    _bytes[staID] = new sumAndMean();
+  }
+}
+
+// 
+////////////////////////////////////////////////////////////////////////////
+void bncFigureLate::slotNewData(const QByteArray staID, double mlate) {
+  QMutexLocker locker(&_mutex);
+  QMap<QByteArray, sumAndMean*>::const_iterator it = _bytes.find(staID);
+  if (it != _bytes.end()) {
+    it.value()->_sum += mlate;
+  }
+}
+
+// 
+////////////////////////////////////////////////////////////////////////////
+void bncFigureLate::slotNextAnimationFrame() {
+  QMutexLocker locker(&_mutex);
+
+  const static int MAXCOUNTER = 10;
+
+  ++_counter;
+
+  // If counter reaches its maximal value, compute the mean value
+  // ------------------------------------------------------------
+  if (_counter == MAXCOUNTER) {
+    _maxLate = 0.0;
+    QMapIterator<QByteArray, sumAndMean*> it(_bytes);
+    while (it.hasNext()) {
+      it.next();
+      it.value()->_mean = it.value()->_sum / _counter;
+      it.value()->_sum  = 0.0;
+      if (it.value()->_mean > _maxLate) {
+        _maxLate = it.value()->_mean;
+      }
+    }
+    _counter = 0;
+  }
+
+  update();
+
+  QTimer::singleShot(1000, this, SLOT(slotNextAnimationFrame()));
+}
+
+// 
+////////////////////////////////////////////////////////////////////////////
+void bncFigureLate::paintEvent(QPaintEvent *) {
+
+  int xMin =   0;
+  int xMax = 640;
+  int yMin =   0;
+  int yMax = 140;
+  float xLine = .60;
+
+  QPainter painter(this);
+
+  QFont font;
+  font.setPointSize(int(font.QFont::pointSize()*0.8));
+  painter.setFont(font);
+
+  // y-axis
+  // ------
+  int yLength = int((yMax-yMin)*xLine) - (yMin+10);
+  painter.drawLine(xMin+50, int((yMax-yMin)*xLine), xMin+50, yMin+10);
+
+  QString maxLateStr;
+  if      (8.0 * _maxLate < 1e3) {
+    maxLateStr = QString("%1 ms  ").arg(int(8.0 * _maxLate));
+    painter.drawText(0, int((yMax-yMin)*xLine)-5, xMin+50,15,Qt::AlignRight,tr("0 ms  "));
+  }
+  else {
+    maxLateStr = QString("%1 sec  ").arg(int(8.0 * _maxLate / 1.e3));
+    painter.drawText(0, int((yMax-yMin)*xLine)-5, xMin+50,15,Qt::AlignRight,tr("0 sec  "));
+  }
+
+  if(_maxLate > 0.0) {
+    painter.drawText(0, yMin+25-5, xMin+50,15,Qt::AlignRight,maxLateStr);
+  }
+
+  // x-axis
+  // ------
+  painter.drawLine(xMin+50, int((yMax-yMin)*xLine), xMax*3, int((yMax-yMin)*xLine));
+
+  int anchor = 0;
+  QMapIterator<QByteArray, sumAndMean*> it(_bytes);
+  while (it.hasNext()) {
+    it.next();
+    QByteArray staID = it.key();
+
+    int xx = xMin+70+anchor*12;
+    int yy = int(yLength * (it.value()->_mean / _maxLate));
+
+    painter.save();
+    painter.translate(xx-13, int(yMax-yMin)*xLine+65);
+    painter.rotate(-90);
+    painter.drawText(0,0,65,50,Qt::AlignRight,staID.left(5) + "   ");
+    painter.restore();
+
+    if(_maxLate > 0.0) {
+      QColor color = QColor::fromRgb(_rgb[0][anchor],_rgb[1][anchor],_rgb[2][anchor]);
+      painter.fillRect(xx-13, int((yMax-yMin)*xLine)-yy, 9, yy, 
+                       QBrush(color,Qt::SolidPattern));
+    }
+
+    anchor++;
+  }
+}
+
Index: trunk/BNC/bncfigurelate.h
===================================================================
--- trunk/BNC/bncfigurelate.h	(revision 1972)
+++ trunk/BNC/bncfigurelate.h	(revision 1972)
@@ -0,0 +1,57 @@
+// Part of BNC, a utility for retrieving decoding and
+// converting GNSS data streams from NTRIP broadcasters.
+//
+// Copyright (C) 2007
+// German Federal Agency for Cartography and Geodesy (BKG)
+// http://www.bkg.bund.de
+// Czech Technical University Prague, Department of Geodesy
+// http://www.fsv.cvut.cz
+//
+// Email: euref-ip@bkg.bund.de
+//
+// 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, version 2.
+//
+// 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, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+#ifndef BNCFIGURELATE_H
+#define BNCFIGURELATE_H
+
+#include <QtGui>
+
+class bncFigureLate : public QWidget {
+  Q_OBJECT
+ public:
+  bncFigureLate(QWidget *parent);
+  ~bncFigureLate();
+  void updateMountPoints();
+ public slots:
+  void slotNewData(const QByteArray staID, double mlate);
+ protected:
+  void paintEvent(QPaintEvent *event);
+ private slots:
+  void slotNextAnimationFrame();
+ private:
+  class sumAndMean {
+   public:
+    sumAndMean() {_mean = 0.0; _sum = 0.0;}
+    ~sumAndMean() {}
+    double _mean;
+    double _sum;
+  };
+  QMap<QByteArray, sumAndMean*> _bytes;
+  QMutex                        _mutex;
+  int                           _counter;
+  double                        _maxLate;
+  int                           _rgb[3][1001];
+};
+
+#endif
Index: trunk/BNC/bncgetthread.cpp
===================================================================
--- trunk/BNC/bncgetthread.cpp	(revision 1971)
+++ trunk/BNC/bncgetthread.cpp	(revision 1972)
@@ -425,4 +425,5 @@
 
       emit newLatency(_staID, _latencyChecker->meanLatency());
+      printf("%s: Mean latency in bncgetthread: %f ms\n", _staID.data(), _latencyChecker->meanLatency());
 
       scanRTCM();            
Index: trunk/BNC/bncgetthread.h
===================================================================
--- trunk/BNC/bncgetthread.h	(revision 1971)
+++ trunk/BNC/bncgetthread.h	(revision 1972)
@@ -75,9 +75,9 @@
  signals:
    void newBytes(QByteArray staID, double nbyte);
+   void newLatency(QByteArray staID, double mlate);
    void newObs(QByteArray staID, bool firstObs, p_obs obs);
    void newAntCrd(QByteArray staID, double xx, double yy, double zz, QByteArray antType);
    void newMessage(QByteArray msg, bool showOnScreen);
    void getThreadFinished(QByteArray staID);
-   void newLatency(QByteArray staID, double meanLatency);
 
  protected:
Index: trunk/BNC/bncwindow.cpp
===================================================================
--- trunk/BNC/bncwindow.cpp	(revision 1971)
+++ trunk/BNC/bncwindow.cpp	(revision 1972)
@@ -54,4 +54,5 @@
 #include "bncsettings.h"
 #include "bncfigure.h"
+#include "bncfigurelate.h"
 
 using namespace std;
@@ -64,4 +65,5 @@
 
   _bncFigure = new bncFigure(this);
+  _bncFigureLate = new bncFigureLate(this);
 
   int ww = QFontMetrics(this->font()).width('w');
@@ -354,4 +356,5 @@
   _log->setWhatsThis(tr("Records of BNC's activities are shown in the 'Log' tab. The message log covers the communication status between BNC and the NTRIP broadcaster as well as any problems that occur in the communication link, stream availability, stream delay, stream conversion etc."));
   _bncFigure->setWhatsThis(tr("The bandwidth consumtion per stream is shown in the 'Throughput' tab in bits per second (bps) or kilo bits per second (kbps)."));
+  _bncFigureLate->setWhatsThis(tr("Latency"));
   _ephV3CheckBox->setWhatsThis(tr("The default format for output of RINEX Navigation data containing Broadcast Ephemeris is RINEX Version 2.11. Select 'Version 3' if you want to output the ephemeris in RINEX Version 3 format."));
   _rnxV3CheckBox->setWhatsThis(tr("The default format for RINEX Observation files is RINEX Version 2.11. Select 'Version 3' if you want to save the observations in RINEX Version 3 format."));
@@ -399,4 +402,5 @@
   _loggroup->addTab(_log,tr("Log"));
   _loggroup->addTab(_bncFigure,tr("Throughput"));
+  _loggroup->addTab(_bncFigureLate,tr("Latency"));
 
   // Proxy Tab
@@ -1108,4 +1112,5 @@
 
   _bncFigure->updateMountPoints();
+  _bncFigureLate->updateMountPoints();
   _caster->slotReadMountPoints();
 }
@@ -1233,5 +1238,6 @@
         connect(thread, SIGNAL(newBytes(QByteArray, double)),
                 _bncFigure, SLOT(slotNewData(QByteArray, double)));
-
+        connect(thread, SIGNAL(newLatency(QByteArray, double)),
+                _bncFigureLate, SLOT(slotNewData(QByteArray, double)));
         break;
       }
Index: trunk/BNC/bncwindow.h
===================================================================
--- trunk/BNC/bncwindow.h	(revision 1971)
+++ trunk/BNC/bncwindow.h	(revision 1972)
@@ -48,4 +48,5 @@
 
 class bncFigure;
+class bncFigureLate;
 
 class bncWindow : public QMainWindow {
@@ -156,4 +157,5 @@
     QTabWidget* _loggroup;
     bncFigure*  _bncFigure;
+    bncFigureLate*  _bncFigureLate;
 
     bncCaster* _caster;
Index: trunk/BNC/latencychecker.cpp
===================================================================
--- trunk/BNC/latencychecker.cpp	(revision 1971)
+++ trunk/BNC/latencychecker.cpp	(revision 1972)
@@ -332,4 +332,5 @@
                   .arg(_numGaps)
                   .toAscii(), true) );
+                _meanLatency = _sumLat/_numLat*1000.;
               } else {
                 emit( newMessage(QString("%1: Mean latency %2 sec, min %3, max %4, rms %5, %6 epochs")
@@ -341,6 +342,6 @@
                   .arg(_numLat)
                   .toAscii(), true) );
+                _meanLatency = _sumLat/_numLat*1000.;
               }
-              _meanLatency = _sumLat/_numLat;
             }
             _meanDiff  = _diffSecGPS / _numLat;
@@ -435,4 +436,5 @@
               .arg(_numGaps);
               emit(newMessage(QString(_staID + late ).toAscii(), true) );
+              _meanLatency = _sumLat/_numLat*1000.;
             } 
             else {
@@ -444,6 +446,6 @@
               .arg(_numLat);
               emit(newMessage(QString(_staID + late ).toAscii(), true) );
+              _meanLatency = _sumLat/_numLat*1000.;
             }
-            _meanLatency = _sumLat/_numLat;
           }
           _meanDiff = int(_diffSecGPS)/_numLat;
