diff options
Diffstat (limited to 'tderadio3/plugins/recording/recording-datamonitor.cpp')
-rw-r--r-- | tderadio3/plugins/recording/recording-datamonitor.cpp | 278 |
1 files changed, 278 insertions, 0 deletions
diff --git a/tderadio3/plugins/recording/recording-datamonitor.cpp b/tderadio3/plugins/recording/recording-datamonitor.cpp new file mode 100644 index 0000000..f2bbe8e --- /dev/null +++ b/tderadio3/plugins/recording/recording-datamonitor.cpp @@ -0,0 +1,278 @@ +/*************************************************************************** + recording-monitor-widget.cpp - description + ------------------- + begin : So Sep 7 2003 + copyright : (C) 2003 by Martin Witte + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * * + * 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; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "recording-datamonitor.h" +//#include "recording-context.h" +#include <math.h> + +#include <tqpainter.h> +#include <tqimage.h> +#include <tqpixmap.h> +#include <kimageeffect.h> // fading, blending, ... +#include <kpixmapio.h> // fast conversion between TQPixmap/TQImage +#include <limits.h> +#include <stdlib.h> + +#include <klocale.h> + +#define CHANNEL_H_MIN 20 +#define BLOCK_W_MIN 10 +#define W_MIN (20 * (BLOCK_W_MIN)) + +RecordingDataMonitor::RecordingDataMonitor(TQWidget *parent, const char *name) + : TQFrame(parent, name), + m_channelsMax(NULL), + m_channelsAvg(NULL), + m_maxValue(INT_MAX), + m_channels(0), + m_pActiveBlocks(NULL) +{ + setFrameStyle(Box | Sunken); + setLineWidth(1); + setMidLineWidth(1); + + setChannels(2); + + setColors(TQColor(20, 244, 20), + TQColor(10, 117, 10)); + + setSizePolicy(TQSizePolicy(TQSizePolicy::Expanding, TQSizePolicy::Expanding)); +} + + +RecordingDataMonitor::~RecordingDataMonitor() +{ + if (m_channelsMax) delete[] m_channelsMax; + if (m_channelsAvg) delete[] m_channelsAvg; + if (m_pActiveBlocks) delete[] m_pActiveBlocks; +} + + + +// own stuff + +void RecordingDataMonitor::setChannels(int n) +{ + if (n != m_channels) { + if (m_channelsMax) delete[] m_channelsMax; + if (m_channelsAvg) delete[] m_channelsAvg; + if (m_pActiveBlocks) delete[] m_pActiveBlocks; + m_channels = n > 0 ? n : 0; + if (m_channels > 0) { + m_channelsMax = new int[m_channels]; + m_channelsAvg = new double[m_channels]; + m_pActiveBlocks = new int[m_channels]; + for (int i = 0; i < m_channels; ++i) { + m_pActiveBlocks[i] = 0; + } + } else { + m_channelsMax = NULL; + m_channelsAvg = NULL; + m_pActiveBlocks = NULL; + } + } + + for (int i = 0; i < m_channels; ++i) { + m_channelsMax[i] = 0; + m_channelsAvg[i] = 0; + } + setMinimumSize(TQSize(W_MIN, (m_channels + 1 )* CHANNEL_H_MIN)); +} + + +// QT/KDE ... + +void RecordingDataMonitor::drawContents(TQPainter *painter) +{ + if (painter) + internalDrawContents(*painter, true); +} + +void RecordingDataMonitor::internalDrawContents(TQPainter &painter, bool repaintAll) +{ + if (m_channels <= 0) return; + TQRect r = contentsRect(); + + TQPen activePen (colorGroup().color(TQColorGroup::Text), 1); + TQPen inactivePen (colorGroup().color(TQColorGroup::Mid), 1); + TQBrush activeBrush = colorGroup().brush(TQColorGroup::Text); + TQBrush inactiveBrush = colorGroup().brush(TQColorGroup::Mid); + TQBrush yellowBrush(TQColor(255,255,0)); + TQBrush orangeBrush(TQColor(255,192,0)); + TQBrush redBrush (TQColor(255,0, 0)); + + + double ranges [5] = { 0.75, 0.83, 0.91, 1.0, 999 }; + TQBrush *brushes[5] = { &activeBrush, &yellowBrush, &orangeBrush, &redBrush, &redBrush }; + + painter.setBrush( isEnabled() ? activeBrush : inactiveBrush); + + int nBlocks = (r.width()-1) / BLOCK_W_MIN; + int xoffs = (r.width()-1) % BLOCK_W_MIN; + int chHeight = (r.height()-1-CHANNEL_H_MIN) / m_channels; + int yoffs = (r.height()-1) % m_channels; + + double min_dB = 20*log10(1 / (double)m_maxValue ); + + int x0 = xoffs/2 + r.top(); + int y = yoffs/2 + r.left(); + for (int c = 0; c < m_channels; ++c) { + int x = x0; + + + int startBlock = 0; + int endBlock = nBlocks - 1; + int oldActiveBlocks = m_pActiveBlocks[c]; + + double dBMax = isEnabled() ? 20*log10(m_channelsMax[c] / (double)m_maxValue ) : min_dB; + + m_pActiveBlocks[c] = m_channelsMax[c] ? (int)rint(nBlocks * (min_dB - dBMax) / min_dB) : 0; + + if (!repaintAll) { + if (oldActiveBlocks > m_pActiveBlocks[c]) { + startBlock = m_pActiveBlocks[c]; + endBlock = oldActiveBlocks - 1; + } else { + startBlock = oldActiveBlocks; + endBlock = m_pActiveBlocks[c]-1; + } + } + + int range = 0; + + x += BLOCK_W_MIN * startBlock; + for (int b = startBlock; b <= endBlock; ++b) { + while (b >= nBlocks * ranges[range]) ++range; + painter.fillRect(x+1, y+1, BLOCK_W_MIN-1, chHeight-1, + b < m_pActiveBlocks[c] ? *brushes[range] : inactiveBrush); + x += BLOCK_W_MIN; + } + + y += chHeight; + } + + if (repaintAll) { + TQFont f("Helvetica"); + painter.setPen (activePen); + f.setPixelSize(CHANNEL_H_MIN); + painter.setFont(f); + + int maxW = TQFontMetrics(f).width(i18n("%1 dB").arg((int)min_dB)); + int delta_dB = 5; + while (abs((long)min_dB) / delta_dB * maxW * 2 > r.width()) delta_dB *= 2; + + for (int dB = 0; dB >= min_dB; dB -= delta_dB) { + TQString txt = i18n("%1 dB").arg(dB); + int w = TQFontMetrics(f).width(txt); + int x = x0 + (int)(nBlocks * BLOCK_W_MIN * (min_dB - dB) / min_dB) - w; + if (x < x0) continue; + painter.drawText(x, y + CHANNEL_H_MIN, txt); + } + } +} + + +bool RecordingDataMonitor::setColors(const TQColor &activeText, + const TQColor &button) +{ + m_colorActiveText = activeText; + m_colorButton = button; + + TQPalette pl = palette(); + TQColorGroup cg = pl.inactive(); + + TQBrush fg = cg.brush(TQColorGroup::Foreground), + btn = cg.brush(TQColorGroup::Button), + lgt = cg.brush(TQColorGroup::Light), + drk = cg.brush(TQColorGroup::Dark), + mid = cg.brush(TQColorGroup::Mid), + txt = cg.brush(TQColorGroup::Text), + btx = cg.brush(TQColorGroup::BrightText), + bas = cg.brush(TQColorGroup::Base), + bg = cg.brush(TQColorGroup::Background); + + fg.setColor (m_colorActiveText); + btn.setColor(m_colorButton); + lgt.setColor(m_colorButton.light(180)); + drk.setColor(m_colorButton.light( 50)); + mid.setColor(m_colorButton.light( 75)); + txt.setColor(m_colorActiveText); + btx.setColor(m_colorActiveText); + bas.setColor(m_colorButton); + bg.setColor (m_colorButton); + + TQColorGroup ncg(fg, btn, lgt, drk, mid, txt, btx, bas, bg); + pl.setInactive(ncg); + pl.setActive(ncg); + setPalette(pl); + + if (parentWidget() && parentWidget()->backgroundPixmap() ){ + KPixmapIO io; + TQImage i = io.convertToImage(*parentWidget()->backgroundPixmap()); + KImageEffect::fade(i, 0.5, colorGroup().color(TQColorGroup::Dark)); + setPaletteBackgroundPixmap(io.convertToPixmap(i)); + setBackgroundOrigin(WindowOrigin); + } else { + setBackgroundColor(colorGroup().color(TQColorGroup::Button)); + } + + return true; +} + + +bool RecordingDataMonitor::noticeSoundStreamData(SoundStreamID /*id*/, + const SoundFormat &sf, const char *data, size_t size, size_t &/*consumed_size*/, + const SoundMetaData &/*md*/ +) +{ + if (!isEnabled()) + return false; + int nSamples = size / sf.frameSize(); + int sample_size = sf.sampleSize(); + + int bias = 0; + setChannels(sf.m_Channels); + int old_max = m_maxValue; + m_maxValue = sf.maxValue(); + if (!sf.m_IsSigned) { + m_maxValue /= 2; + bias = -m_maxValue; + } + + int c = 0; + for (int s = 0; s < nSamples; ++s, ++c, data += sample_size) { + if (c >= m_channels) c -= m_channels; // avoid slow c = s % m_channels + + int &m = m_channelsMax[c]; + int x = abs(sf.convertSampleToInt(data, false) + bias); + if (m < x) m = x; + m_channelsAvg[c] += x; + } + for (int i = 0; i < m_channels; ++i) + m_channelsAvg[i] /= nSamples; + + TQPainter paint(this); + if (m_maxValue != old_max) { + repaint(true); + } else { + internalDrawContents(paint, false); + } + return true; +} + + +#include "recording-datamonitor.moc" |