You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdemultimedia/noatun/modules/kjofol-skin/kjvis.cpp

539 lines
13 KiB

/***************************************************************************
kjvis.cpp - Visualizations used in the KJ<EFBFBD>fol-GUI
--------------------------------------
Maintainer: Stefan Gehn <metz AT gehn.net>
***************************************************************************/
// local includes
#include "kjvis.h"
#include "kjprefs.h"
// system includes
#include <math.h>
//qt includes
#include <tqpainter.h>
#include <tqsize.h>
//kde includes
#include <kdebug.h>
#include <kglobal.h>
#include <kconfig.h>
#include <kpixmapeffect.h>
#include <kpixmap.h>
// noatun includes
#include <noatun/player.h>
#define _KJ_GRADIENT_DIFF 130
/*******************************************
* KJFFTScope
*******************************************/
void KJVisScope::swapScope(Visuals newOne)
{
//kdDebug(66666) << k_funcinfo << endl;
TQStringList line = parent()->item("analyzerwindow");
KJLoader *p=parent();
p->removeChild(this);
delete this;
KJLoader::kjofol->prefs()->setVisType ( newOne );
KJWidget *w = 0;
switch (newOne)
{
case Null:
w = new KJNullScope(line, p);
break;
case FFT:
w = new KJFFT(line, p);
break;
case StereoFFT:
w = new KJStereoFFT(line, p);
break;
case Mono:
w = new KJScope(line, p);
break;
};
p->addChild(w);
}
/*******************************************
* KJNullScope
*******************************************/
KJNullScope::KJNullScope(const TQStringList &l, KJLoader *parent)
: KJVisScope(parent)
{
int x = l[1].toInt();
int y = l[2].toInt();
int xs = l[3].toInt() - x;
int ys = l[4].toInt() - y;
// background under vis
TQPixmap tmp = parent->pixmap(parent->item("backgroundimage")[1]);
mBack = new KPixmap ( TQSize(xs,ys) );
bitBlt( mBack, 0, 0, &tmp, x, y, xs, ys, TQt::CopyROP );
setRect ( x, y, xs, ys );
repaint();
}
void KJNullScope::paint(TQPainter *p, const TQRect &)
{
// just redraw the background
bitBlt ( p->device(), rect().topLeft(), mBack, TQRect(0,0,-1,-1), TQt::CopyROP );
}
bool KJNullScope::mousePress(const TQPoint &)
{
return true;
}
void KJNullScope::mouseRelease(const TQPoint &, bool in)
{
if (!in) // only do something if users is still inside the button
return;
parent()->repaint(rect(), false);
swapScope(FFT);
}
void KJNullScope::readConfig()
{
// kdDebug(66666) << "[KJNullScope] readConfig()" << endl;
Visuals v = (Visuals) KJLoader::kjofol->prefs()->visType();
if ( v != Null )
{
parent()->repaint(rect(), false);
swapScope ( v );
}
}
/*************************************************
* KJFFT - Analyzer like visualization, mono
*************************************************/
KJFFT::KJFFT(const TQStringList &l, KJLoader *parent)
: KJVisScope(parent), MonoFFTScope(50), mGradient(0)
{
int x = l[1].toInt();
int y = l[2].toInt();
int xs = l[3].toInt()-x;
int ys = l[4].toInt()-y;
// each bar will be 1px wide
mMultiples=1;
if ( parent->exist("analyzercolor") )
{
TQStringList &col = parser()["analyzercolor"];
mColor.setRgb ( col[1].toInt(), col[2].toInt(), col[3].toInt() );
}
else // TODO: what should be default colors for Vis?
{
mColor.setRgb ( 255, 255, 255 ); // white is default
}
// background under vis
TQPixmap tmp = parent->pixmap(parent->item("backgroundimage")[1]);
mBack = new KPixmap ( TQSize(xs,ys) );
bitBlt( mBack, 0, 0, &tmp, x, y, xs, ys, TQt::CopyROP );
mAnalyzer = new KPixmap ( TQSize(xs,ys) );
bitBlt( mAnalyzer, 0, 0, &tmp, x, y, xs, ys, TQt::CopyROP );
// create a gradient for the bars going from 30% lighter to 30% darker than mColor
mGradient = new KPixmap ( TQSize(xs,ys) );
KPixmapEffect::gradient ( *mGradient, mColor.light(_KJ_GRADIENT_DIFF),
mColor.dark(_KJ_GRADIENT_DIFF), KPixmapEffect::VerticalGradient );
setRect (x,y,xs,ys);
setBands(magic(xs/mMultiples));
readConfig(); // read our config settings
start();
}
void KJFFT::scopeEvent(float *d, int size)
{
if ( !napp->player()->isPlaying() ) // don't draw if we aren't playing (either paused or stopped)
{
if ( napp->player()->isStopped() ) // clear vis-window if playing has been stopped
parent()->repaint(rect(), false);
return;
}
int x = 0;
int h = rect().height();
TQBitmap mGradientMask ( rect().width(), h, true );
TQPainter mask( &mGradientMask );
float *start = d ;
float *end = d + size /*- 1*/;
// loop creating the mask for vis-gradient
for ( ; start < end; ++start )
{
// 5 has been 8 before and I have no idea how this scaling works :/
// FIXME: somebody please make it scale to 100% of height,
// I guess that would be nicer to look at
// float n = log((*start)+1) * (float)h * 5;
float n = log((*start)+1) * (float)h * 5;
int amp=(int)n;
// range check
if ( amp < 0 ) amp = 0;
else if ( amp > h ) amp = h;
// make a part of the analyzer-gradient visible
mask.fillRect ( x, (h-amp), mMultiples, amp, TQt::color1 );
x += mMultiples;
}
// done creating our mask
// draw background of vis into it
bitBlt ( mAnalyzer, 0, 0, mBack, 0, 0, -1, -1, TQt::CopyROP );
// draw the analyzer
mGradient->setMask(mGradientMask);
bitBlt ( mAnalyzer, 0, 0, mGradient, 0, 0, -1, -1, TQt::CopyROP );
repaint();
}
void KJFFT::paint(TQPainter *p, const TQRect &)
{
// put that thing on screen
if ( !napp->player()->isStopped() )
bitBlt ( p->device(), rect().topLeft(), mAnalyzer, TQRect(0,0,-1,-1), TQt::CopyROP );
}
bool KJFFT::mousePress(const TQPoint &)
{
return true;
}
void KJFFT::mouseRelease(const TQPoint &, bool in)
{
if (!in) // only do something if users is still inside the button
return;
stop();
parent()->repaint(rect(), false);
swapScope(Mono);
}
void KJFFT::readConfig()
{
// kdDebug(66666) << "[KJFFT] readConfig()" << endl;
Visuals v = (Visuals) KJLoader::kjofol->prefs()->visType();
if ( v != FFT )
{
stop();
parent()->repaint(rect(), false);
swapScope ( v );
return;
}
mTimerValue = KJLoader::kjofol->prefs()->visTimerValue();
setInterval( mTimerValue );
}
/*************************************************
* KJStereoFFT - Analyzer like visualization, stereo
*************************************************/
KJStereoFFT::KJStereoFFT(const TQStringList &l, KJLoader *parent)
: KJVisScope(parent), StereoFFTScope(50), mGradient(0)
{
//kdDebug(66666) << k_funcinfo << endl;
int x = l[1].toInt();
int y = l[2].toInt();
int xs = l[3].toInt()-x;
int ys = l[4].toInt()-y;
// each bar will be 1px wide
mMultiples=1;
if ( parent->exist("analyzercolor") )
{
TQStringList &col = parser()["analyzercolor"];
mColor.setRgb ( col[1].toInt(), col[2].toInt(), col[3].toInt() );
}
else // TODO: what should be default colors for Vis?
{
mColor.setRgb ( 255, 255, 255 ); // white is default
}
// background under vis
TQPixmap tmp = parent->pixmap(parent->item("backgroundimage")[1]);
mBack = new KPixmap ( TQSize(xs,ys) );
bitBlt( mBack, 0, 0, &tmp, x, y, xs, ys, TQt::CopyROP );
mAnalyzer = new KPixmap ( TQSize(xs,ys) );
bitBlt( mAnalyzer, 0, 0, &tmp, x, y, xs, ys, TQt::CopyROP );
// create a gradient for the bars going from 30% lighter to 30% darker than mColor
mGradient = new KPixmap ( TQSize(xs,ys) );
KPixmapEffect::gradient ( *mGradient, mColor.light(_KJ_GRADIENT_DIFF),
mColor.dark(_KJ_GRADIENT_DIFF), KPixmapEffect::VerticalGradient );
setRect (x,y,xs,ys);
setBands(magic(xs/mMultiples));
readConfig(); // read our config settings
start();
}
void KJStereoFFT::scopeEvent(float *left, float *right, int len)
{
if ( !napp->player()->isPlaying() ) // don't draw if we aren't playing (either paused or stopped)
{
if ( napp->player()->isStopped() ) // clear vis-window if playing has been stopped
parent()->repaint(rect(), false);
return;
}
unsigned int h = rect().height();
int hh = (int)(rect().height()/2);
TQBitmap mGradientMask ( rect().width(), h, true );
TQPainter mask( &mGradientMask );
float *start = left;
float *end = left + len;
float n = 0.0;
int amp = 0;
int x = 0;
// loop creating the mask for vis-gradient
for ( ; start < end; ++start )
{
n = log((*start)+1) * (float)hh * 5;
amp = (int)n;
// range check
if ( amp < 0 ) amp = 0;
else if ( amp > hh ) amp = hh;
// make a part of the analyzer-gradient visible
mask.fillRect ( x, (h-amp), mMultiples, amp, TQt::color1 );
x += mMultiples;
}
// done creating our mask
start = right;
end = right + len;
x = 0;
// loop creating the mask for vis-gradient
for ( ; start < end; ++start )
{
n = log((*start)+1) * (float)hh * 5;
amp = (int)n;
// range check
if ( amp < 0 ) amp = 0;
else if ( amp > hh ) amp = hh;
// make a part of the analyzer-gradient visible
mask.fillRect ( x, 0, mMultiples, amp, TQt::color1 );
x += mMultiples;
}
// draw background of vis into it
bitBlt ( mAnalyzer, 0, 0, mBack, 0, 0, -1, -1, TQt::CopyROP );
// draw the analyzer
mGradient->setMask(mGradientMask);
bitBlt ( mAnalyzer, 0, 0, mGradient, 0, 0, -1, -1, TQt::CopyROP );
repaint();
}
void KJStereoFFT::paint(TQPainter *p, const TQRect &)
{
// put that thing on screen
if ( !napp->player()->isStopped() )
bitBlt ( p->device(), rect().topLeft(), mAnalyzer, TQRect(0,0,-1,-1), TQt::CopyROP );
}
bool KJStereoFFT::mousePress(const TQPoint &)
{
return true;
}
void KJStereoFFT::mouseRelease(const TQPoint &, bool in)
{
if (!in) // only do something if users is still inside the button
return;
stop();
parent()->repaint(rect(), false);
swapScope(Null);
}
void KJStereoFFT::readConfig()
{
//kdDebug(66666) << k_funcinfo << endl;
Visuals v = (Visuals) KJLoader::kjofol->prefs()->visType();
if ( v != StereoFFT )
{
stop();
parent()->repaint(rect(), false);
swapScope ( v );
return;
}
setInterval(KJLoader::kjofol->prefs()->visTimerValue());
}
/*************************************************
* KJScope - oscilloscope like visualization
*************************************************/
KJScope::KJScope(const TQStringList &l, KJLoader *parent)
: KJVisScope(parent), MonoScope(50)/*, blurnum(0), mOsci(0)*/
{
int x=l[1].toInt();
int y=l[2].toInt();
int xs = mWidth = l[3].toInt()-x;
int ys = mHeight = l[4].toInt()-y;
blurnum = 0;
// kdDebug(66666) << "Analyzer Window " << x << "," << y << " " << mWidth << "," << mHeight << endl;
if ( parent->exist("analyzercolor") )
{
TQStringList &col = parser()["analyzercolor"];
mColor.setRgb ( col[1].toInt(), col[2].toInt(), col[3].toInt() );
}
else // FIXME: what should be default colors for Vis?
mColor.setRgb ( 255, 255, 255 );
// background under vis
TQPixmap tmp = parent->pixmap(parent->item("backgroundimage")[1]);
mBack = new KPixmap ( TQSize(xs,ys) );
bitBlt( mBack, 0, 0, &tmp, x, y, xs, ys, TQt::CopyROP );
mOsci = new KPixmap ( TQSize(xs,ys) );
bitBlt( mOsci, 0, 0, &tmp, x, y, xs, ys, TQt::CopyROP );
// create a gradient
mGradient = new KPixmap ( TQSize(xs,ys) );
KPixmapEffect::gradient ( *mGradient, mColor.light(_KJ_GRADIENT_DIFF),
mColor.dark(_KJ_GRADIENT_DIFF), KPixmapEffect::VerticalGradient );
setRect ( x, y, xs, ys );
// set the samplewidth to the largest integer divisible by mWidth
setSamples ( xs );
readConfig();
start();
}
void KJScope::scopeEvent(float *d, int size)
{
if ( !napp->player()->isPlaying() )
{
if ( napp->player()->isStopped() )
{
bitBlt ( mOsci, 0, 0, mBack, 0, 0, -1, -1, TQt::CopyROP );
repaint();
}
return;
}
float *start = d;
float *end = d + size;
int heightHalf = rect().height()/2 /* -1 */;
int x = 0;
TQPainter tempP( mOsci );
if ( blurnum == 3 )
{ // clear whole Vis
bitBlt ( mOsci, 0, 0, mBack, 0, 0, -1, -1, TQt::CopyROP );
tempP.setPen( mColor.light(110) ); // 10% lighter than mColor
blurnum=0;
}
else
{
blurnum++;
// reduce color for blur-effect
tempP.setPen( mColor.dark(90+(10*blurnum)) ); // darken color
}
for ( ; start < end; ++start )
{
float n = (*start) * (float)heightHalf;
int amp = (int)n;
// range check
if ( amp > heightHalf ) amp = heightHalf;
else if ( amp < -heightHalf) amp = -heightHalf;
// draw
// tempP.drawLine(x, heightHalf, x, heightHalf+amp);
if ( amp > 0 )
{
bitBlt ( tempP.device(), TQPoint(x,heightHalf), mGradient, TQRect(x,heightHalf,1,amp), TQt::CopyROP );
}
else
{
amp = -amp;
bitBlt ( tempP.device(), TQPoint(x,heightHalf-amp), mGradient, TQRect(x,(heightHalf-amp),1,amp), TQt::CopyROP );
}
x++;
}
repaint();
}
void KJScope::paint(TQPainter *p, const TQRect &)
{
// put that thing on screen
bitBlt ( p->device(), rect().topLeft(), mOsci, TQRect(0,0,-1,-1), TQt::CopyROP );
}
bool KJScope::mousePress(const TQPoint &)
{
return true;
}
void KJScope::mouseRelease(const TQPoint &, bool in)
{
if (!in) // only do something if users is still inside the button
return;
stop();
parent()->repaint(rect(), false);
swapScope(/*Null*/ StereoFFT);
}
void KJScope::readConfig()
{
// kdDebug(66666) << "[KJScope] readConfig()" << endl;
Visuals v = (Visuals) KJLoader::kjofol->prefs()->visType();
if ( v != Mono )
{
stop();
parent()->repaint(rect(), false);
swapScope ( v );
return;
}
mTimerValue = KJLoader::kjofol->prefs()->visTimerValue();
setInterval( mTimerValue );
}