Rivendellaudio/lib/rdsegmeter.cpp
Fred Gleason 796e1bebc3 2018-08-07 Fred Gleason <fredg@paravelsystems.com>
* Removed the 'pam_rd' plug-in.
	* Removed rdchunk(1).
	* Upgraded Qt3 to Qt4.
2018-08-07 10:09:49 -04:00

507 lines
11 KiB
C++

// rdsegmeter.cpp
//
// An audio meter display widget.
//
// (C) Copyright 2002-2003,2016 Fred Gleason <fredg@paravelsystems.com>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU Library General Public License
// version 2 as published by the Free Software Foundation.
//
// 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 <qwidget.h>
#include <qstring.h>
#include <qcolor.h>
#include <qpainter.h>
#include <qpushbutton.h>
#include <qsize.h>
//Added by qt3to4:
#include <QPixmap>
#include <QPaintEvent>
#include <stdio.h>
#include <qslider.h>
#include <q3buttongroup.h>
#include <qsizepolicy.h>
#include <qmessagebox.h>
#include <rdsegmeter.h>
RDSegMeter::RDSegMeter(RDSegMeter::Orientation o,QWidget *parent)
: QWidget(parent)
{
orient=o;
setBackgroundColor(Qt::black);
dark_low_color=QColor(DEFAULT_DARK_LOW_COLOR);
dark_high_color=QColor(DEFAULT_DARK_HIGH_COLOR);
dark_clip_color=QColor(DEFAULT_DARK_CLIP_COLOR);
low_color=QColor(DEFAULT_LOW_COLOR);
high_color=QColor(DEFAULT_HIGH_COLOR);
clip_color=QColor(DEFAULT_CLIP_COLOR);
high_threshold=-14;
clip_threshold=0;
seg_size=2;
seg_gap=1;
range_min=-3000;
range_max=0;
solid_bar=-10000;
floating_bar=-10000;
seg_mode=RDSegMeter::Independent;
peak_timer=new QTimer(this,"peak_timer");
connect(peak_timer,SIGNAL(timeout()),this,SLOT(peakData()));
}
QSize RDSegMeter::sizeHint() const
{
return QSize(0,0);
}
QSizePolicy RDSegMeter::sizePolicy() const
{
return QSizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed);
}
void RDSegMeter::setRange(int min,int max)
{
range_min=min;
range_max=max;
repaint(false);
}
void RDSegMeter::setDarkLowColor(QColor color)
{
if(dark_low_color!=color) {
dark_low_color=color;
repaint(false);
}
}
void RDSegMeter::setDarkHighColor(QColor color)
{
if(dark_high_color!=color) {
dark_high_color=color;
repaint(false);
}
}
void RDSegMeter::setDarkClipColor(QColor color)
{
if(dark_clip_color!=color) {
dark_clip_color=color;
repaint(false);
}
}
void RDSegMeter::setLowColor(QColor color)
{
if(low_color!=color) {
low_color=color;
repaint(false);
}
}
void RDSegMeter::setHighColor(QColor color)
{
if(high_color!=color) {
high_color=color;
repaint(false);
}
}
void RDSegMeter::setClipColor(QColor color)
{
if(clip_color!=color) {
clip_color=color;
repaint(false);
}
}
void RDSegMeter::setHighThreshold(int level)
{
if(high_threshold!=level) {
high_threshold=level;
repaint(false);
}
}
void RDSegMeter::setClipThreshold(int level)
{
if(clip_threshold!=level) {
clip_threshold=level;
repaint(false);
}
}
RDSegMeter::Mode RDSegMeter::mode() const
{
return seg_mode;
}
void RDSegMeter::setMode(RDSegMeter::Mode mode)
{
seg_mode=mode;
switch(seg_mode) {
case RDSegMeter::Independent:
if(peak_timer->isActive()) {
peak_timer->stop();
}
break;
case RDSegMeter::Peak:
if(!peak_timer->isActive()) {
peak_timer->start(PEAK_HOLD_TIME);
}
break;
}
}
void RDSegMeter::setSolidBar(int level)
{
if((seg_mode==RDSegMeter::Independent)&&(solid_bar!=level)) {
solid_bar=level;
repaint(false);
}
}
void RDSegMeter::setFloatingBar(int level)
{
if((seg_mode==RDSegMeter::Independent)&&(solid_bar!=level)) {
floating_bar=level;
repaint(false);
}
}
void RDSegMeter::setPeakBar(int level)
{
if((seg_mode==RDSegMeter::Peak)&&(solid_bar!=level)) {
solid_bar=level;
if(solid_bar>floating_bar) {
floating_bar=solid_bar;
}
if(solid_bar<range_min) {
floating_bar=solid_bar;
}
repaint(false);
}
}
void RDSegMeter::setSegmentSize(int size)
{
if(seg_size!=size) {
seg_size=size;
repaint(false);
}
}
void RDSegMeter::setSegmentGap(int gap)
{
if(seg_gap!=gap) {
seg_gap=gap;
repaint(false);
}
}
void RDSegMeter::paintEvent(QPaintEvent *paintEvent)
{
int op_pt;
int low_region,high_region,clip_region,float_region;
int dark_low_region=0;
int dark_high_region=0;
int dark_clip_region=0;
QColor float_color;
//
// Setup
//
QPixmap pix(this->size());
pix.fill(this,0,0);
int seg_total=seg_size+seg_gap;
QPainter *p=new QPainter(&pix);
low_region=0;
high_region=0;
clip_region=0;
p->setBrush(low_color);
p->setPen(low_color);
//
// Set Orientation
//
switch(orient) {
case RDSegMeter::Left:
case RDSegMeter::Up:
p->translate(width(),height());
p->rotate(180);
break;
default:
break;
}
//
// The low range
//
if(solid_bar>high_threshold) {
op_pt=high_threshold;
}
else {
op_pt=solid_bar;
}
switch(orient) {
case RDSegMeter::Left:
case RDSegMeter::Right:
low_region=(int)((double)(op_pt-range_min)/
(double)(range_max-range_min)*width()/seg_total);
if(op_pt>range_min) {
for(int i=0;i<low_region;i++) {
p->fillRect(i*seg_total,0,seg_size,height(),low_color);
}
}
break;
case RDSegMeter::Down:
case RDSegMeter::Up:
low_region=(int)((double)(op_pt-range_min)/
(double)(range_max-range_min)*height()/seg_total);
if(op_pt>range_min) {
for(int i=0;i<low_region;i++) {
p->fillRect(0,i*seg_total,width(),seg_size,low_color);
}
}
break;
}
//
// The high range
//
if(solid_bar>clip_threshold) {
op_pt=clip_threshold;
}
else {
op_pt=solid_bar;
}
switch(orient) {
case RDSegMeter::Left:
case RDSegMeter::Right:
high_region=(int)((double)(op_pt-high_threshold)/
(double)(range_max-range_min)*width()/seg_total);
if(op_pt>high_threshold) {
for(int i=low_region;i<low_region+high_region;i++) {
p->fillRect(i*seg_total,0,seg_size,height(),high_color);
}
}
break;
case RDSegMeter::Down:
case RDSegMeter::Up:
high_region=(int)((double)(op_pt-high_threshold)/
(double)(range_max-range_min)*height()/seg_total);
if(op_pt>high_threshold) {
for(int i=low_region;i<low_region+high_region;i++) {
p->fillRect(0,i*seg_total,width(),seg_size,high_color);
}
}
break;
}
//
// The clip range
//
if(solid_bar>range_max) {
op_pt=range_max;
}
else {
op_pt=solid_bar;
}
switch(orient) {
case RDSegMeter::Left:
case RDSegMeter::Right:
clip_region=(int)((double)(op_pt-clip_threshold)/
(double)(range_max-range_min)*width()/seg_total);
if(op_pt>clip_threshold) {
for(int i=low_region+high_region;
i<low_region+high_region+clip_region;i++) {
p->fillRect(i*seg_total,0,seg_size,height(),clip_color);
}
}
break;
case RDSegMeter::Down:
case RDSegMeter::Up:
clip_region=(int)((double)(op_pt-range_min)/
(double)(range_max-range_min)*height()/seg_total);
if(op_pt>clip_threshold) {
for(int i=low_region+high_region;
i<low_region+high_region+clip_region;i++) {
p->fillRect(0,i*seg_total,width(),seg_size,clip_color);
}
}
break;
}
//
// The dark low range
//
switch(orient) {
case RDSegMeter::Left:
case RDSegMeter::Right:
dark_low_region=(int)((double)(high_threshold-range_min)/
(double)(range_max-range_min)*width()/seg_total);
if(op_pt<high_threshold) {
for(int i=low_region;i<dark_low_region;i++) {
p->fillRect(i*seg_total,0,seg_size,height(),dark_low_color);
}
}
break;
case RDSegMeter::Down:
case RDSegMeter::Up:
dark_low_region=(int)((double)(high_threshold-range_min)/
(double)(range_max-range_min)*height()/seg_total);
if(op_pt<high_threshold) {
for(int i=low_region;i<dark_low_region;i++) {
p->fillRect(0,i*seg_total,width(),seg_size,dark_low_color);
}
}
break;
}
//
// The dark high range
//
if(solid_bar>=high_threshold) {
op_pt=low_region+high_region;
}
else {
op_pt=dark_low_region;
}
switch(orient) {
case RDSegMeter::Left:
case RDSegMeter::Right:
dark_high_region=(int)((double)(clip_threshold-range_min)/
(double)(range_max-range_min)*width()/seg_total);
if(solid_bar<clip_threshold) {
for(int i=op_pt;
i<dark_high_region;i++) {
p->fillRect(i*seg_total,0,seg_size,height(),dark_high_color);
}
}
break;
case RDSegMeter::Down:
case RDSegMeter::Up:
dark_high_region=(int)((double)(clip_threshold-range_min)/
(double)(range_max-range_min)*height()/seg_total);
if(solid_bar<clip_threshold) {
for(int i=op_pt;i<dark_high_region;i++) {
p->fillRect(0,i*seg_total,width(),seg_size,dark_high_color);
}
}
break;
}
//
// The dark clip range
//
if(solid_bar>clip_threshold) {
op_pt=low_region+high_region+clip_region;
}
else {
op_pt=dark_high_region;
}
switch(orient) {
case RDSegMeter::Left:
case RDSegMeter::Right:
dark_clip_region=(int)((double)(range_max-range_min)/
(double)(range_max-range_min)*width()/seg_total);
if(solid_bar<range_max) {
for(int i=op_pt;i<dark_clip_region;i++) {
p->fillRect(i*seg_total,0,seg_size,height(),dark_clip_color);
}
}
break;
case RDSegMeter::Down:
case RDSegMeter::Up:
dark_clip_region=(int)((double)(range_max-range_min)/
(double)(range_max-range_min)*height()/seg_total);
if(solid_bar<range_max) {
for(int i=op_pt;
i<dark_clip_region;i++) {
p->fillRect(0,i*seg_total,width(),seg_size,dark_clip_color);
}
}
break;
}
//
// The floating segment
//
if(floating_bar>solid_bar) {
if(floating_bar<=high_threshold) {
float_color=low_color;
}
if((floating_bar>high_threshold)&&(floating_bar<=clip_threshold)) {
float_color=high_color;
}
if(floating_bar>clip_threshold) {
float_color=clip_color;
}
switch(orient) {
case RDSegMeter::Left:
case RDSegMeter::Right:
float_region=(int)((double)(floating_bar-range_min)/
(double)(range_max-range_min)*width());
float_region=seg_total*(float_region/seg_total);
p->fillRect(float_region,0,seg_size,height(),float_color);
break;
case RDSegMeter::Down:
case RDSegMeter::Up:
float_region=(int)((double)(floating_bar-range_min)/
(double)(range_max-range_min)*height());
float_region=seg_total*(float_region/seg_total);
p->fillRect(0,float_region,width(),seg_size,float_color);
break;
}
}
p->end();
p->begin(this);
p->drawPixmap(0,0,pix);
p->end();
delete p;
}
void RDSegMeter::peakData()
{
floating_bar=solid_bar;
repaint(false);
}