UltraGrid
UltraGrid Low-Latency High-Resolution Transmission System
Loading...
Searching...
No Matches
VuMeterWidget Class Reference

#include <vuMeterWidget.hpp>

Inheritance diagram for VuMeterWidget:
Inheritance graph
Collaboration diagram for VuMeterWidget:
Collaboration graph

Classes

struct  PeakMaximum
 

Public Slots

void updateVal ()
 

Public Member Functions

 VuMeterWidget (QWidget *parent)
 
void parseLine (std::string_view line)
 
void setControlPort (ControlPort *controlPort)
 
void setOnRightSide (bool side)
 
void setParsePrefix (std::string_view prefix)
 

Protected Member Functions

void paintEvent (QPaintEvent *paintEvent)
 

Private Types

using clock = std::chrono::steady_clock
 

Private Slots

void onControlPortConnect ()
 

Private Member Functions

void paintMeter (QPainter &, int x, int y, int width, int height, double peak, double rms, double maxPeak)
 
void paintScale (QPainter &, int x, int y, int width, int height, bool leftTicks, bool rightTicks)
 

Private Attributes

double barLevel [max_channels]
 
int channels = 0
 
bool connected = false
 
ControlPort * controlPort = nullptr
 
clock::time_point lastUpdate
 
PeakMaximum maximumLevel [max_channels]
 
bool onRightSide = false
 
std::string parsePrefix = "stats ARECV"
 
double peak [max_channels]
 
double rms [max_channels]
 
double rmsLevel [max_channels]
 
QTimer timer
 
int updatesPerSecond
 

Static Private Attributes

static const int max_channels = 8
 

Detailed Description

Definition at line 14 of file vuMeterWidget.hpp.

Member Typedef Documentation

◆ clock

using VuMeterWidget::clock = std::chrono::steady_clock
private

Definition at line 29 of file vuMeterWidget.hpp.

Constructor & Destructor Documentation

◆ VuMeterWidget()

VuMeterWidget::VuMeterWidget ( QWidget * parent)

Definition at line 25 of file vuMeterWidget.cpp.

25 :
26 QWidget(parent),
27 peak {0.0},
28 rms {0.0},
29 barLevel {0.0},
30 rmsLevel {0.0},
32{
33 connect(&timer, SIGNAL(timeout()), this, SLOT(updateVal()));
34 timer.start(1000/updatesPerSecond);
35}
double rmsLevel[max_channels]
double rms[max_channels]
double peak[max_channels]
double barLevel[max_channels]
const char * parent
Definition settings.cpp:198

References timer, updatesPerSecond, and updateVal().

Here is the call graph for this function:

Member Function Documentation

◆ onControlPortConnect

void VuMeterWidget::onControlPortConnect ( )
privateslot

Definition at line 113 of file vuMeterWidget.cpp.

113 {
114 assert(controlPort);
115 controlPort->writeLine("stats on\r\n");
116 lastUpdate = clock::time_point();
117}
void writeLine(std::string_view line)
ControlPort * controlPort
clock::time_point lastUpdate

References controlPort, lastUpdate, and ControlPort::writeLine().

Referenced by setControlPort().

Here is the call graph for this function:

◆ paintEvent()

void VuMeterWidget::paintEvent ( QPaintEvent * paintEvent)
protected

Definition at line 225 of file vuMeterWidget.cpp.

225 {
226 const int scaleWidth = 30;
227
228 const int meterCount = std::max(1, channels);
229
230 const int meterWidth = (width() - scaleWidth) / meterCount;
231
232 QPainter painter(this);
233
234 if(meterCount % 2 != 0){
235 int scaleX = onRightSide ? 0 : meterCount * meterWidth;
236 int metersStartX = onRightSide ? scaleWidth : 0;
237
238 for(int i = 0; i < meterCount; i++){
239 paintMeter(painter,
240 metersStartX + i * meterWidth,
241 meterVerticalPad,
242 meterWidth,
243 height() - meterVerticalPad * 2,
244 barLevel[i],
245 rmsLevel[i],
246 maximumLevel[i].val);
247 }
248
249 paintScale(painter,
250 scaleX,
251 0,
252 scaleWidth,
253 height(),
256 } else {
257 int i = 0;
258 for(; i < meterCount / 2; i++){
259 paintMeter(painter,
260 i * meterWidth,
261 meterVerticalPad,
262 meterWidth,
263 height() - meterVerticalPad * 2,
264 barLevel[i],
265 rmsLevel[i],
266 maximumLevel[i].val);
267 }
268
269 paintScale(painter,
270 i * meterWidth,
271 0,
272 scaleWidth,
273 height(),
274 true,
275 true);
276
277 for(; i < meterCount; i++){
278 paintMeter(painter,
279 i * meterWidth + scaleWidth,
280 meterVerticalPad,
281 meterWidth,
282 height() - meterVerticalPad * 2,
283 barLevel[i],
284 rmsLevel[i],
285 maximumLevel[i].val);
286 }
287
288 }
289
290}
int void * val
void paintMeter(QPainter &, int x, int y, int width, int height, double peak, double rms, double maxPeak)
void paintScale(QPainter &, int x, int y, int width, int height, bool leftTicks, bool rightTicks)
PeakMaximum maximumLevel[max_channels]

References barLevel, channels, maximumLevel, onRightSide, paintMeter(), paintScale(), rmsLevel, and val.

Here is the call graph for this function:

◆ paintMeter()

void VuMeterWidget::paintMeter ( QPainter & painter,
int x,
int y,
int width,
int height,
double peak,
double rms,
double maxPeak )
private

Definition at line 119 of file vuMeterWidget.cpp.

127{
128 const int meterBarPadHorizontal = 1;
129 const int in_width = width - meterBarPadHorizontal * 2;
130 const int in_full_height = height - meterBarPad * 2;
131
132 int barHeight = in_full_height * (peak / 100);
133 int rmsHeight = in_full_height * (rms / 100);
134 int maxPeakHeight = in_full_height * (maxPeak / 100);
135
136 QLinearGradient gradient(0, 0, in_width, in_full_height);
137 gradient.setColorAt(0, Qt::red);
138 gradient.setColorAt(0.25, Qt::yellow);
139 gradient.setColorAt(0.5, Qt::green);
140 gradient.setColorAt(1, Qt::green);
141 QBrush brush(gradient);
142
143 using namespace std::chrono_literals;
144 bool enabled = connected && (clock::now() - lastUpdate <= 2s);
145
146 painter.fillRect(x, y + 1, width, height - 2, enabled ? Qt::black : Qt::gray);
147 if(!enabled)
148 return;
149
150 painter.fillRect(x + meterBarPadHorizontal,
151 y + meterBarPad + (in_full_height - barHeight),
152 in_width, barHeight,
153 brush);
154
155 int maxPos = y + meterBarPad + (in_full_height - maxPeakHeight);
156 QPen maxLevelPen(brush, 1);
157 painter.setPen(maxLevelPen);
158 painter.drawLine(x + meterBarPadHorizontal, maxPos, x + in_width, maxPos);
159
160 QPen rmsPen(Qt::blue);
161 rmsPen.setWidth(4);
162 painter.setPen(rmsPen);
163 int pos = y + meterBarPad + (in_full_height - rmsHeight);
164 painter.drawLine(x + meterBarPadHorizontal, pos, x + in_width, pos);
165}
bool enabled
Definition settings.cpp:197

References connected, enabled, lastUpdate, peak, and rms.

Referenced by paintEvent().

◆ paintScale()

void VuMeterWidget::paintScale ( QPainter & painter,
int x,
int y,
int width,
int height,
bool leftTicks,
bool rightTicks )
private

Definition at line 167 of file vuMeterWidget.cpp.

174{
175 const int barHeight = height - meterVerticalPad * 2 - meterBarPad * 2;
176 const int barStart = y + meterVerticalPad + meterBarPad;
177 const float stepPx = (float) barHeight / std::fabs(zeroLevel);
178
179 painter.setPen(connected ? Qt::black : Qt::gray);
180 int i = 0;
181
182 int textPosX;
183 if(leftTicks && rightTicks){
184 textPosX = x + width / 2 - 8;
185 } else if(leftTicks){
186 textPosX = x + width - 16;
187 } else {
188 textPosX = x;
189 }
190
191 for(float y = barStart; y <= barStart + barHeight + 0.1; y += stepPx){
192 static const int lineLenghtSmall = 2;
193 static const int lineLenghtMid = 4;
194 static const int lineLenghtLarge = 6;
195 static const int drawThreshold = 4;
196 if(i % 10 == 0){
197 if(leftTicks) painter.drawLine(x, y, x + lineLenghtLarge, y);
198 if(rightTicks) painter.drawLine(x + width - lineLenghtLarge, y, x + width, y);
199 painter.drawText(QRect(textPosX, y - 6, 16, 12), Qt::AlignCenter,QString::number(i));
200 } else if(i % 5 == 0){
201 if(leftTicks) painter.drawLine(x, y, x + lineLenghtMid, y);
202 if(rightTicks) painter.drawLine(x + width - lineLenghtMid, y, x + width, y);
203 } else if(stepPx >= drawThreshold){
204 if(leftTicks) painter.drawLine(x, y, x + lineLenghtSmall, y);
205 if(rightTicks) painter.drawLine(x + width - lineLenghtSmall, y, x + width, y);
206 }
207
208 i++;
209 }
210
211 if(!connected){
212 int iconDim = 32;
213 QIcon icon = style()->standardIcon(QStyle::SP_MessageBoxWarning);
214 QPixmap pixmap = icon.pixmap(iconDim,iconDim);
215 painter.eraseRect(x+width/2 - (iconDim+4)/2, y + height / 2 - (iconDim+4)/2,
216 iconDim+4, iconDim+4);
217 painter.drawPixmap(x+width/2 - iconDim/2, y + height / 2 - iconDim/2,
218 iconDim, iconDim,
219 pixmap,
220 0, 0,
221 iconDim, iconDim);
222 }
223}

References connected.

Referenced by paintEvent().

◆ parseLine()

void VuMeterWidget::parseLine ( std::string_view line)

Definition at line 37 of file vuMeterWidget.cpp.

37 {
38 if(!sv_is_prefix(line, parsePrefix))
39 return;
40
41 line.remove_prefix(parsePrefix.size());
42
43 for(channels = 0; !line.empty() && channels < max_channels; channels++){
44 auto rmsTag = tokenize(line, ' ');
45 if(!sv_is_prefix(rmsTag, "volrms"))
46 return;
47 auto rms_sv = tokenize(line, ' ');
48
49 auto peakTag = tokenize(line, ' ');
50 if(!sv_is_prefix(peakTag, "volpeak"))
51 return;
52 auto peak_sv = tokenize(line, ' ');
53
54 double ch_rms = 0;
55 double ch_peak = 0;
56 if(!parse_num(rms_sv, ch_rms)
57 || !parse_num(peak_sv, ch_peak))
58 {
59 return;
60 }
61
62 peak[channels] = ch_peak;
63 rms[channels] = ch_rms;
64 }
65
66 lastUpdate = clock::now();
67}
static const int max_channels
std::string parsePrefix
std::string_view tokenize(std::string_view &str, char delim, char quot)
Tokenizer for string_view.
bool parse_num(std::string_view sv, T &res, int base=10)
bool sv_is_prefix(std::string_view haystack, std::string_view needle)

References channels, lastUpdate, max_channels, parse_num(), parsePrefix, peak, rms, sv_is_prefix(), and tokenize().

Referenced by setControlPort().

Here is the call graph for this function:

◆ setControlPort()

void VuMeterWidget::setControlPort ( ControlPort * controlPort)

Definition at line 69 of file vuMeterWidget.cpp.

69 {
70 this->controlPort = controlPort;
71
72 using namespace std::placeholders;
75}
void addLineCallback(LineCallback callback)
void connected()
void parseLine(std::string_view line)
void onControlPortConnect()

References ControlPort::addLineCallback(), ControlPort::connected(), controlPort, onControlPortConnect(), and parseLine().

Here is the call graph for this function:

◆ setOnRightSide()

void VuMeterWidget::setOnRightSide ( bool side)
inline

Definition at line 23 of file vuMeterWidget.hpp.

23{ onRightSide = side; }

References onRightSide.

◆ setParsePrefix()

void VuMeterWidget::setParsePrefix ( std::string_view prefix)

Definition at line 77 of file vuMeterWidget.cpp.

77 {
78 parsePrefix = prefix;
79}

References parsePrefix.

◆ updateVal

void VuMeterWidget::updateVal ( )
slot

Definition at line 81 of file vuMeterWidget.cpp.

81 {
82 const double fallSpeed = 200.0;
83 const double maximumPeakFallSpeed = 10.0;
84 auto maximumPeakHoldTime = std::chrono::seconds(2);
85
86 connected = controlPort->getState() == QAbstractSocket::ConnectedState;
87
88 for(int i = 0; i < channels; i++){
89 auto& maxPeak = maximumLevel[i];
90 auto now = clock::now();
91
92 barLevel[i] = std::max(barLevel[i] - fallSpeed / updatesPerSecond, 0.0);
93 rmsLevel[i] = std::max(rmsLevel[i] - fallSpeed / updatesPerSecond, 0.0);
94 if(now - maxPeak.ts > maximumPeakHoldTime){
95 maxPeak.val = std::max(maxPeak.val - maximumPeakFallSpeed / updatesPerSecond, 0.0);
96 }
97
98 double newPeakHeight = 100 - std::max(peak[i], zeroLevel) * (100 / zeroLevel);
99 double newRmsHeight = 100 - std::max(rms[i], zeroLevel) * (100 / zeroLevel);
100
101 barLevel[i] = std::max(barLevel[i], newPeakHeight);
102 rmsLevel[i] = std::max(rmsLevel[i], newRmsHeight);
103
104 if(barLevel[i] >= maxPeak.val){
105 maxPeak.val = barLevel[i];
106 maxPeak.ts = now;
107 }
108 }
109
110 update();
111}
QAbstractSocket::SocketState getState() const

References barLevel, channels, connected, controlPort, ControlPort::getState(), maximumLevel, peak, rms, rmsLevel, and updatesPerSecond.

Referenced by VuMeterWidget().

Here is the call graph for this function:

Member Data Documentation

◆ barLevel

double VuMeterWidget::barLevel[max_channels]
private

Definition at line 42 of file vuMeterWidget.hpp.

Referenced by paintEvent(), and updateVal().

◆ channels

int VuMeterWidget::channels = 0
private

Definition at line 38 of file vuMeterWidget.hpp.

Referenced by paintEvent(), parseLine(), and updateVal().

◆ connected

bool VuMeterWidget::connected = false
private

Definition at line 53 of file vuMeterWidget.hpp.

Referenced by paintMeter(), paintScale(), and updateVal().

◆ controlPort

ControlPort* VuMeterWidget::controlPort = nullptr
private

Definition at line 52 of file vuMeterWidget.hpp.

Referenced by onControlPortConnect(), setControlPort(), and updateVal().

◆ lastUpdate

clock::time_point VuMeterWidget::lastUpdate
private

Definition at line 50 of file vuMeterWidget.hpp.

Referenced by onControlPortConnect(), paintMeter(), and parseLine().

◆ max_channels

const int VuMeterWidget::max_channels = 8
staticprivate

Definition at line 35 of file vuMeterWidget.hpp.

Referenced by parseLine().

◆ maximumLevel

PeakMaximum VuMeterWidget::maximumLevel[max_channels]
private

Definition at line 44 of file vuMeterWidget.hpp.

Referenced by paintEvent(), and updateVal().

◆ onRightSide

bool VuMeterWidget::onRightSide = false
private

Definition at line 46 of file vuMeterWidget.hpp.

Referenced by paintEvent(), and setOnRightSide().

◆ parsePrefix

std::string VuMeterWidget::parsePrefix = "stats ARECV"
private

Definition at line 36 of file vuMeterWidget.hpp.

Referenced by parseLine(), and setParsePrefix().

◆ peak

double VuMeterWidget::peak[max_channels]
private

Definition at line 39 of file vuMeterWidget.hpp.

Referenced by paintMeter(), parseLine(), and updateVal().

◆ rms

double VuMeterWidget::rms[max_channels]
private

Definition at line 40 of file vuMeterWidget.hpp.

Referenced by paintMeter(), parseLine(), and updateVal().

◆ rmsLevel

double VuMeterWidget::rmsLevel[max_channels]
private

Definition at line 43 of file vuMeterWidget.hpp.

Referenced by paintEvent(), and updateVal().

◆ timer

QTimer VuMeterWidget::timer
private

Definition at line 48 of file vuMeterWidget.hpp.

Referenced by VuMeterWidget().

◆ updatesPerSecond

int VuMeterWidget::updatesPerSecond
private

Definition at line 49 of file vuMeterWidget.hpp.

Referenced by VuMeterWidget(), and updateVal().


The documentation for this class was generated from the following files: