270 lines
8.2 KiB
C++
270 lines
8.2 KiB
C++
//=============================================================================
|
|
// Awl
|
|
// Audio Widget Library
|
|
// $Id:$
|
|
//
|
|
// Copyright (C) 2002-2006 by Werner Schweer and others
|
|
//
|
|
// This program is free software; you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
//=============================================================================
|
|
|
|
#include "fastlog.h"
|
|
#include "mslider.h"
|
|
|
|
namespace Awl {
|
|
|
|
//---------------------------------------------------------
|
|
// MeterSlider
|
|
//---------------------------------------------------------
|
|
|
|
MeterSlider::MeterSlider(QWidget* parent)
|
|
: VolSlider(parent)
|
|
{
|
|
setAttribute(Qt::WA_NoSystemBackground, true);
|
|
_channel = 0;
|
|
yellowScale = -16; //-10;
|
|
redScale = 0;
|
|
_meterWidth = _scaleWidth * 3;
|
|
setChannel(1);
|
|
setMinimumHeight(50);
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// sizeHint
|
|
//---------------------------------------------------------
|
|
|
|
QSize MeterSlider::sizeHint() const
|
|
{
|
|
int w = _meterWidth + _scaleWidth + _scaleWidth + 30;
|
|
return orientation() == Qt::Vertical ? QSize(w, 200) : QSize(200, w);
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// setChannel
|
|
//---------------------------------------------------------
|
|
|
|
void MeterSlider::setChannel(int n)
|
|
{
|
|
if (n > _channel) {
|
|
for (int i = _channel; i < n; ++i) {
|
|
meterval.push_back(0.0f);
|
|
meterPeak.push_back(0.0f);
|
|
}
|
|
}
|
|
_channel = n;
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// setMeterVal
|
|
//---------------------------------------------------------
|
|
|
|
void MeterSlider::setMeterVal(int channel, double v, double peak)
|
|
{
|
|
bool mustRedraw = false;
|
|
if (meterval[channel] != v) {
|
|
meterval[channel] = v;
|
|
mustRedraw = true;
|
|
}
|
|
if (peak != meterPeak[channel]) {
|
|
meterPeak[channel] = peak;
|
|
mustRedraw = true;
|
|
}
|
|
if (mustRedraw) {
|
|
int kh = sliderSize().height();
|
|
int mh = height() - kh;
|
|
update(20, kh / 2, _meterWidth-1, mh);
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// resetPeaks
|
|
// reset peak and overflow indicator
|
|
//---------------------------------------------------------
|
|
|
|
void MeterSlider::resetPeaks()
|
|
{
|
|
for (int i = 0; i < _channel; ++i)
|
|
meterPeak[i] = meterval[i];
|
|
update();
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// resizeEvent
|
|
//---------------------------------------------------------
|
|
|
|
void MeterSlider::resizeEvent(QResizeEvent* /*ev*/)
|
|
{
|
|
int h = height();
|
|
int kh = sliderSize().height();
|
|
int mh = h - kh;
|
|
int mw = _meterWidth / _channel;
|
|
|
|
onPm = QPixmap(mw, mh);
|
|
offPm = QPixmap(mw, mh);
|
|
|
|
double range = maxValue() - minValue();
|
|
int h1 = mh - lrint((maxValue() - redScale) * mh / range);
|
|
int h2 = mh - lrint((maxValue() - yellowScale) * mh / range);
|
|
|
|
QColor yellowRed;
|
|
yellowRed.setHsv(QColor(Qt::yellow).hue()-8,
|
|
QColor(Qt::yellow).saturation(),
|
|
QColor(Qt::yellow).value());
|
|
QColor yellRedRed;
|
|
yellRedRed.setHsv(QColor(Qt::yellow).hue()-16,
|
|
QColor(Qt::yellow).saturation(),
|
|
QColor(Qt::yellow).value());
|
|
|
|
QLinearGradient linearGrad(QPointF(0, 0), QPointF(0, mh));
|
|
linearGrad.setColorAt(0, Qt::red);
|
|
linearGrad.setColorAt(1-(double)(h1-5)/(double)mh, yellRedRed);
|
|
linearGrad.setColorAt(1-(double)(h1-6)/(double)mh, yellowRed);
|
|
linearGrad.setColorAt(1-(double)h2/(double)mh, Qt::yellow);
|
|
linearGrad.setColorAt(1, Qt::green);
|
|
|
|
QColor darkYellowRed;
|
|
darkYellowRed.setHsv(QColor(Qt::darkYellow).hue()-8,
|
|
QColor(Qt::darkYellow).saturation(),
|
|
QColor(Qt::darkYellow).value());
|
|
QColor darkYellRedRed;
|
|
darkYellRedRed.setHsv(QColor(Qt::darkYellow).hue()-16,
|
|
QColor(Qt::darkYellow).saturation(),
|
|
QColor(Qt::darkYellow).value());
|
|
QLinearGradient linearDarkGrad(QPointF(0, 0), QPointF(0, mh));
|
|
linearDarkGrad.setColorAt(0, Qt::darkRed);
|
|
linearDarkGrad.setColorAt(1-(double)(h1-5)/(double)mh, darkYellRedRed);
|
|
linearDarkGrad.setColorAt(1-(double)(h1-6)/(double)mh, darkYellowRed);
|
|
linearDarkGrad.setColorAt(1-(double)h2/(double)mh, Qt::darkYellow);
|
|
linearDarkGrad.setColorAt(1, Qt::darkGreen);
|
|
|
|
QPainter p;
|
|
p.begin(&onPm);
|
|
p.fillRect(0, 0, mw, mh, linearGrad);
|
|
p.end();
|
|
p.begin(&offPm);
|
|
p.fillRect(0, 0, mw, mh, linearDarkGrad);
|
|
p.end();
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// paintEvent
|
|
//---------------------------------------------------------
|
|
|
|
void MeterSlider::paintEvent(QPaintEvent* ev)
|
|
{
|
|
int h = height();
|
|
int kh = sliderSize().height();
|
|
int mh = h - kh;
|
|
|
|
double range = maxValue() - minValue();
|
|
int ppos = int(mh * (_value - minValue()) / range);
|
|
if (_invert)
|
|
ppos = mh - ppos;
|
|
|
|
QPainter p(this);
|
|
p.setRenderHint(QPainter::Antialiasing, false);
|
|
|
|
//---------------------------------------------------
|
|
// draw meter
|
|
//---------------------------------------------------
|
|
|
|
int mw = _meterWidth / _channel;
|
|
int x = 20;
|
|
int y1 = kh / 2;
|
|
int y3 = h - y1;
|
|
|
|
p.setPen(QPen(Qt::white, 2));
|
|
|
|
for (int i = 0; i < _channel; ++i) {
|
|
int h = mh - (lrint(fast_log10(meterval[i]) * -20.0f * mh / range));
|
|
if (h < 0)
|
|
h = 0;
|
|
else if (h > mh)
|
|
h = mh;
|
|
|
|
p.drawPixmap(x, y1+mh-h, mw, h, onPm, 0, mh-h, mw, h);
|
|
p.drawPixmap(x, y1, mw, mh-h, offPm, 0, 0, mw, mh-h);
|
|
|
|
//---------------------------------------------------
|
|
// draw peak line
|
|
//---------------------------------------------------
|
|
|
|
h = mh - (lrint(fast_log10(meterPeak[i]) * -20.0f * mh / range));
|
|
if (h > mh)
|
|
h = mh;
|
|
if (h > 0)
|
|
p.drawLine(x, y3-h, x+mw, y3-h);
|
|
|
|
x += mw;
|
|
}
|
|
|
|
// optimize common case:
|
|
if (ev->rect() == QRect(20, kh/2, _meterWidth-1, mh))
|
|
return;
|
|
|
|
QColor sc(isEnabled() ? _scaleColor : Qt::gray);
|
|
QColor svc(isEnabled() ? _scaleValueColor : Qt::gray);
|
|
p.setBrush(svc);
|
|
|
|
//---------------------------------------------------
|
|
// draw scale
|
|
//---------------------------------------------------
|
|
|
|
int y2 = h - (ppos + y1);
|
|
p.fillRect(x, y1, _scaleWidth, y2-y1, sc);
|
|
p.fillRect(x, y2, _scaleWidth, y3-y2, svc);
|
|
|
|
//---------------------------------------------------
|
|
// draw tick marks
|
|
//---------------------------------------------------
|
|
|
|
QFont f(p.font());
|
|
f.setPointSize(6);
|
|
p.setFont(f);
|
|
p.setPen(QPen(Qt::darkGray, 2));
|
|
QFontMetrics fm(f);
|
|
int xt = 20 - fm.width("00") - 5;
|
|
|
|
QString s;
|
|
for (int i = 10; i < 70; i += 10) {
|
|
h = y1 + lrint(i * mh / range);
|
|
s.setNum(i - 10);
|
|
p.drawText(xt, h - 3, s);
|
|
p.drawLine(15, h, 20, h);
|
|
}
|
|
|
|
//---------------------------------------------------
|
|
// draw slider
|
|
//---------------------------------------------------
|
|
|
|
x += _scaleWidth/2;
|
|
p.setPen(QPen(svc, 0));
|
|
p.translate(QPointF(x, y2));
|
|
p.setRenderHint(QPainter::Antialiasing, true);
|
|
p.drawPath(*points);
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// mousePressEvent
|
|
//---------------------------------------------------------
|
|
|
|
void MeterSlider::mousePressEvent(QMouseEvent* ev)
|
|
{
|
|
if (ev->pos().x() < _meterWidth) {
|
|
emit meterClicked();
|
|
return;
|
|
}
|
|
VolSlider::mousePressEvent(ev);
|
|
}
|
|
}
|
|
|