mirror of
https://github.com/overte-org/overte.git
synced 2025-07-14 16:16:33 +02:00
215 lines
7.1 KiB
C++
215 lines
7.1 KiB
C++
//
|
|
// BandwidthMeter.h
|
|
// interface
|
|
//
|
|
// Created by Tobias Schwinger on 6/20/13.
|
|
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
|
//
|
|
|
|
#include "BandwidthMeter.h"
|
|
#include "InterfaceConfig.h"
|
|
|
|
#include "Log.h"
|
|
#include "Util.h"
|
|
|
|
// --- Configuration
|
|
|
|
// Layout:
|
|
//
|
|
// +--- unit label width (e)
|
|
// | +-- unit label horiz. spacing (f)
|
|
// V V
|
|
// | | |
|
|
// +--------+ \ \ Channel
|
|
// Unit +-------+ | Total channel height (a) / height (d)
|
|
// | / ] Channel spacing (b)
|
|
// +----+
|
|
// Unit +------+
|
|
// |
|
|
// ...
|
|
//
|
|
|
|
namespace { // .cpp-local
|
|
|
|
float const CHANNEL_SPACING = 0.125f; // (b) fractional in respect to total channel height
|
|
float const STREAM_SPACING = 0.0625f; // (c) fractional in respect to total channel height
|
|
float const LABEL_CHAR_WIDTH = 0.28f; // (e) fractional in respect to total channel height
|
|
float const LABEL_HORIZ_SPACING = 0.25f; // (f) fractional in respect to total channel height
|
|
|
|
unsigned const FRAME_COLOR = 0xe0e0e0b0;
|
|
unsigned const INDICATOR_COLOR = 0xc0c0c0b0;
|
|
unsigned const VALUE_COLOR = 0xa0a0a0e0;
|
|
float const INDICATOR_BASE = 10.0f;
|
|
float const INDICATOR_LOG_BASE = log(INDICATOR_BASE);
|
|
}
|
|
|
|
BandwidthMeter::ChannelInfo BandwidthMeter::_DEFAULT_CHANNELS[] = {
|
|
{ "Audio" , "Kbps", 1.0 * 1024.0, 80.5, 0x40ff40d0 },
|
|
{ "Avatars" , "KBps", 1.0 * 1024.0, 20.0, 0xffef40c0 },
|
|
{ "Voxels" , "Mbps", 1024.0 * 1024.0, 0.5, 0xd0d0d0a0 }
|
|
};
|
|
|
|
// ---
|
|
|
|
BandwidthMeter::BandwidthMeter() :
|
|
_textRenderer(SANS_FONT_FAMILY, -1, -1, false, TextRenderer::SHADOW_EFFECT) {
|
|
|
|
memcpy(_channels, _DEFAULT_CHANNELS, sizeof(_DEFAULT_CHANNELS));
|
|
}
|
|
|
|
BandwidthMeter::Stream::Stream(float secondsToAverage) :
|
|
_value(0.0f),
|
|
_secsToAverage(secondsToAverage) {
|
|
|
|
gettimeofday(& _prevTime, NULL);
|
|
}
|
|
|
|
void BandwidthMeter::Stream::updateValue(double amount) {
|
|
|
|
// Determine elapsed time
|
|
timeval now;
|
|
gettimeofday(& now, NULL);
|
|
double dt = diffclock(& _prevTime, & now) / 1000.0;
|
|
memcpy(& _prevTime, & now, sizeof(timeval));
|
|
|
|
// Compute approximate average
|
|
_value = glm::mix(_value, amount / dt,
|
|
glm::clamp(dt / _secsToAverage, 0.0, 1.0));
|
|
}
|
|
|
|
static void setColorRGBA(unsigned c) {
|
|
|
|
glColor4ub(GLubyte( c >> 24),
|
|
GLubyte((c >> 16) & 0xff),
|
|
GLubyte((c >> 8) & 0xff),
|
|
GLubyte( c & 0xff));
|
|
}
|
|
|
|
static void renderBox(float w, float h) {
|
|
glBegin(GL_QUADS);
|
|
glVertex2f(0.0f, 0.0f);
|
|
glVertex2f(w, 0.0f);
|
|
glVertex2f(w, h);
|
|
glVertex2f(0.0f, h);
|
|
glEnd();
|
|
}
|
|
|
|
void BandwidthMeter::render(int x, int y, unsigned w, unsigned h) {
|
|
|
|
float channelTotalHeight = float(h) / N_CHANNELS;
|
|
float channelSpacing = CHANNEL_SPACING * channelTotalHeight;
|
|
float channelHeight = channelTotalHeight - channelSpacing;
|
|
float streamSpacing = STREAM_SPACING * channelTotalHeight;
|
|
float streamHeight = (channelHeight - streamSpacing) * 0.5;
|
|
|
|
QFontMetrics const& fontMetrics = _textRenderer.metrics();
|
|
int fontDescent = fontMetrics.descent();
|
|
int labelRenderWidthCaption = 0;
|
|
int labelRenderWidthUnit = 0;
|
|
for (int i = 0; i < N_CHANNELS; ++i) {
|
|
labelRenderWidthCaption = glm::max(labelRenderWidthCaption, fontMetrics.width(_channels[i].caption));
|
|
labelRenderWidthUnit = glm::max(labelRenderWidthUnit, fontMetrics.width(_channels[i].unitCaption));
|
|
}
|
|
int labelRenderWidth = glm::max(labelRenderWidthCaption, labelRenderWidthUnit);
|
|
int labelRenderHeight = fontMetrics.lineSpacing();
|
|
float labelCharWSpaces = float(labelRenderWidth) / float(fontMetrics.width("M"));
|
|
float labelWidth = channelTotalHeight * LABEL_CHAR_WIDTH * labelCharWSpaces;
|
|
float labelHeight = (channelHeight - streamSpacing) * 0.5f;
|
|
|
|
float labelScaleX = labelWidth / float(labelRenderWidth);
|
|
float labelScaleY = labelHeight / float(labelRenderHeight);
|
|
float labelHorizSpacing = channelTotalHeight * LABEL_HORIZ_SPACING;
|
|
|
|
|
|
glPushMatrix();
|
|
|
|
int xMin = x + int(labelWidth + labelHorizSpacing);
|
|
|
|
// Render vertical lines for the frame
|
|
setColorRGBA(FRAME_COLOR);
|
|
glBegin(GL_LINES);
|
|
glVertex2i(xMin - 1, y);
|
|
glVertex2i(xMin - 1, y + h);
|
|
glVertex2i(x + w - 1, y);
|
|
glVertex2i(x + w - 1, y + h);
|
|
glEnd();
|
|
|
|
// Set coordinate center to right edge of bars / top
|
|
glTranslatef(float(xMin), float(y) + channelSpacing * 0.5f, 0.0f);
|
|
|
|
// Determine maximum horizontal length for bars
|
|
float xMax = float(w) - labelWidth - labelHorizSpacing;
|
|
|
|
char fmtBuf[64];
|
|
|
|
for (int i = 0; i < N_CHANNELS; ++i) {
|
|
// ...each channel
|
|
|
|
ChannelInfo& c = channelInfo(i);
|
|
float scaleStep = powf(INDICATOR_BASE, ceil(logf(c.unitsMax) / INDICATOR_LOG_BASE) - 1.0f);
|
|
|
|
float unitsIn = inputStream(i).getValue() / c.unitScale;
|
|
if (unitsIn > c.unitsMax) {
|
|
c.unitsMax += scaleStep;
|
|
}
|
|
float barPosIn = xMax * fmin(unitsIn / c.unitsMax, 1.0f);
|
|
float unitsOut = outputStream(i).getValue() / c.unitScale;
|
|
float barPosOut = xMax * fmin(unitsOut / c.unitsMax, 1.0f);
|
|
|
|
// Render scale indicators
|
|
setColorRGBA(INDICATOR_COLOR);
|
|
for (float meas = scaleStep; meas < c.unitsMax - 0.01f; meas += scaleStep) {
|
|
float pixX = xMax * meas / c.unitsMax;
|
|
glBegin(GL_LINES);
|
|
glVertex2f(pixX, 0);
|
|
glVertex2f(pixX, channelHeight);
|
|
glEnd();
|
|
}
|
|
|
|
// Render captions
|
|
setColorRGBA(c.colorRGBA);
|
|
glPushMatrix();
|
|
glTranslatef(-labelHorizSpacing, channelHeight * 0.5f, 0.0f);
|
|
glScalef(labelScaleX, labelScaleY, 1.0f);
|
|
_textRenderer.draw(-labelRenderWidth, -fontDescent, c.caption);
|
|
_textRenderer.draw(-fontMetrics.width(c.unitCaption), labelRenderHeight - fontDescent, c.unitCaption);
|
|
glPopMatrix();
|
|
|
|
// Render input bar
|
|
renderBox(barPosIn, streamHeight);
|
|
|
|
// Render output value
|
|
glPushMatrix();
|
|
setColorRGBA(VALUE_COLOR);
|
|
glTranslatef(0.0f, streamHeight, 0.0f);
|
|
glScalef(labelScaleX, labelScaleY, 1.0f);
|
|
|
|
sprintf(fmtBuf, "%0.2f in", unitsIn);
|
|
_textRenderer.draw(glm::max(int(barPosIn / labelScaleX) - fontMetrics.width(fmtBuf), 0), -fontDescent, fmtBuf);
|
|
glPopMatrix();
|
|
|
|
// Advance to next stream
|
|
glTranslatef(0.0f, streamHeight + streamSpacing, 0.0f);
|
|
|
|
// Render output bar
|
|
setColorRGBA(c.colorRGBA);
|
|
renderBox(barPosOut, streamHeight);
|
|
|
|
// Render output value
|
|
glPushMatrix();
|
|
setColorRGBA(VALUE_COLOR);
|
|
glTranslatef(0.0f, streamHeight, 0.0f);
|
|
glScalef(labelScaleX, labelScaleY, 1.0f);
|
|
|
|
sprintf(fmtBuf, "%0.2f out", unitsOut);
|
|
_textRenderer.draw(glm::max(int(barPosOut / labelScaleX) - fontMetrics.width(fmtBuf), 0), -fontDescent, fmtBuf);
|
|
glPopMatrix();
|
|
|
|
// Advance to next channel
|
|
glTranslatef(0.0f, streamHeight + channelSpacing, 0.0f);
|
|
}
|
|
|
|
glPopMatrix();
|
|
}
|
|
|
|
|