00001
00002
00003
00004
00005
00006
00007
00008 #include <cmath>
00009 #include <cstdio>
00010 #include <algorithm>
00011 #include <iostream>
00012
00013
00014 #include <qtimer.h>
00015 #include <qpainter.h>
00016 #include <qevent.h>
00017 #include <qapplication.h>
00018 #include <qspinbox.h>
00019 #include <qpixmap.h>
00020 #include <qcursor.h>
00021 #include <qstring.h>
00022 #include <qregexp.h>
00023
00024
00025 #include <mythtv/audiooutput.h>
00026 #include <mythtv/mythcontext.h>
00027 #include <mythtv/mythdialogs.h>
00028
00029
00030 #include "visualize.h"
00031 #include "mainvisual.h"
00032 #include "constants.h"
00033
00034
00035 #include "inlines.h"
00036
00037
00038 using namespace std;
00039
00040 VisFactory* VisFactory::g_pVisFactories = 0;
00041
00042 VisualBase::VisualBase(bool screensaverenable)
00043 : xscreensaverenable(screensaverenable)
00044 {
00045 if (!xscreensaverenable)
00046 gContext->DoDisableScreensaver();
00047 }
00048
00049 VisualBase::~VisualBase()
00050 {
00051
00052
00053
00054
00055
00056 if (!xscreensaverenable)
00057 gContext->DoRestoreScreensaver();
00058 }
00059
00060 void VisualBase::drawWarning(QPainter *p, const QColor &back, const QSize &size, QString warning)
00061 {
00062 p->fillRect(0, 0, size.width(), size.height(), back);
00063 p->setPen(Qt::white);
00064 p->setFont(gContext->GetMediumFont());
00065
00066 QFontMetrics fm(p->font());
00067 int width = fm.width(warning);
00068 int height = fm.height() * (warning.contains("\n") + 1);
00069 int x = size.width() / 2 - width / 2;
00070 int y = size.height() / 2 - height / 2;
00071
00072 for (int offset = 0; offset < height; offset += fm.height()) {
00073 QString l = warning.left(warning.find("\n"));
00074 p->drawText(x, y + offset, width, height, Qt::AlignCenter, l);
00075 warning.remove(0, l.length () + 1);
00076 }
00077 }
00078
00079 MainVisual::MainVisual(QWidget *parent, const char *name)
00080 : QWidget(parent, name), vis(0), meta(0), playing(FALSE), fps(20),
00081 timer (0), bannerTimer(0), info_widget(0)
00082 {
00083 int screenwidth = 0, screenheight = 0;
00084 float wmult = 0, hmult = 0;
00085
00086 gContext->GetScreenSettings(screenwidth, wmult, screenheight, hmult);
00087
00088 setGeometry(0, 0, parent->width(), parent->height());
00089
00090 setFont(gContext->GetBigFont());
00091 setCursor(QCursor(Qt::BlankCursor));
00092
00093 info_widget = new InfoWidget(this);
00094
00095 bannerTimer = new QTimer(this);
00096 connect(bannerTimer, SIGNAL(timeout()), this, SLOT(bannerTimeout()));
00097
00098 timer = new QTimer(this);
00099 connect(timer, SIGNAL(timeout()), this, SLOT(timeout()));
00100 timer->start(1000 / fps);
00101 }
00102
00103 MainVisual::~MainVisual()
00104 {
00105 if (vis)
00106 {
00107 delete vis;
00108 vis = 0;
00109 }
00110
00111 delete info_widget;
00112 info_widget = 0;
00113
00114 delete timer;
00115 timer = 0;
00116
00117 delete bannerTimer;
00118 bannerTimer = 0;
00119
00120 nodes.setAutoDelete(TRUE);
00121 nodes.clear();
00122 }
00123
00124 void MainVisual::setVisual(const QString &name)
00125 {
00126 pixmap.fill(Qt::black);
00127
00128 QString visName, pluginName;
00129
00130 if (name.contains("-"))
00131 {
00132 visName = name.section('-', 0, 0);
00133 pluginName = name.section('-', 1, 1);
00134 }
00135 else
00136 {
00137 visName = name;
00138 pluginName = "";
00139 }
00140
00141 if (vis)
00142 {
00143 delete vis;
00144 vis = NULL;
00145 }
00146
00147 for (const VisFactory* pVisFactory = VisFactory::VisFactories();
00148 pVisFactory; pVisFactory = pVisFactory->next())
00149 {
00150 if (pVisFactory->name() == visName)
00151 {
00152 vis = pVisFactory->create(this, (long int) winId(), pluginName);
00153 vis->resize(size());
00154 fps = vis->getDesiredFPS();
00155 break;
00156 }
00157 }
00158
00159
00160 timer->stop();
00161 timer->start( 1000 / fps );
00162 }
00163
00164 void MainVisual::prepare()
00165 {
00166 nodes.setAutoDelete(TRUE);
00167 nodes.clear();
00168 nodes.setAutoDelete(FALSE);
00169 }
00170
00171 void MainVisual::add(uchar *b, unsigned long b_len, unsigned long w, int c, int p)
00172 {
00173 long len = b_len, cnt;
00174 short *l = 0, *r = 0;
00175
00176 len /= c;
00177 len /= (p / 8);
00178
00179 if (len > 512)
00180 len = 512;
00181
00182 cnt = len;
00183
00184 if (c == 2)
00185 {
00186 l = new short[len];
00187 r = new short[len];
00188
00189 if (p == 8)
00190 stereo16_from_stereopcm8(l, r, b, cnt);
00191 else if (p == 16)
00192 stereo16_from_stereopcm16(l, r, (short *) b, cnt);
00193 }
00194 else if (c == 1)
00195 {
00196 l = new short[len];
00197
00198 if (p == 8)
00199 mono16_from_monopcm8(l, b, cnt);
00200 else if (p == 16)
00201 mono16_from_monopcm16(l, (short *) b, cnt);
00202 }
00203 else
00204 len = 0;
00205
00206 nodes.append(new VisualNode(l, r, len, w));
00207 }
00208
00209 void MainVisual::timeout()
00210 {
00211 bool process = true;
00212 if (parent() != gContext->GetMainWindow()->currentWidget())
00213 {
00214 process = false;
00215 return;
00216 }
00217
00218 VisualNode *node = 0;
00219
00220 if (playing && output())
00221 {
00222 long synctime = output()->GetAudiotime();
00223 mutex()->lock();
00224 VisualNode *prev = 0;
00225 while ((node = nodes.first()))
00226 {
00227 if (node->offset > synctime)
00228 break;
00229 delete prev;
00230 nodes.removeFirst();
00231 prev = node;
00232 }
00233 mutex()->unlock();
00234 node = prev;
00235 }
00236
00237 bool stop = TRUE;
00238 if (vis && process)
00239 stop = vis->process(node);
00240 if (node)
00241 delete node;
00242
00243 if (vis && process)
00244 {
00245 QPainter p(&pixmap);
00246 if (vis->draw(&p, Qt::black))
00247 {
00248 bitBlt(this, 0, 0, &pixmap);
00249 }
00250 }
00251
00252 if (!playing && stop)
00253 timer->stop();
00254 }
00255
00256 void MainVisual::paintEvent(QPaintEvent *)
00257 {
00258 bitBlt(this, 0, 0, &pixmap);
00259 }
00260
00261 void MainVisual::resizeEvent( QResizeEvent *event )
00262 {
00263 pixmap.resize(event->size());
00264 pixmap.fill(backgroundColor());
00265 QWidget::resizeEvent( event );
00266 if ( vis )
00267 vis->resize( size() );
00268
00269 info_widget->setDisplayRect(QRect((int)(pixmap.width() * 0.1),
00270 (int)(pixmap.height() * 0.75),
00271 (int)(pixmap.width() * 0.8),
00272 (int)(pixmap.height() * 0.18)));
00273 }
00274
00275 void MainVisual::customEvent(QCustomEvent *event)
00276 {
00277 switch (event->type())
00278 {
00279 case OutputEvent::Playing:
00280 case OutputEvent::Info:
00281 case OutputEvent::Buffering:
00282 case OutputEvent::Paused:
00283 playing = TRUE;
00284
00285 if (! timer->isActive())
00286 timer->start(1000 / fps);
00287 break;
00288
00289 case OutputEvent::Stopped:
00290 case OutputEvent::Error:
00291 playing = FALSE;
00292 break;
00293
00294 default:
00295 ;
00296 }
00297 }
00298
00299 void MainVisual::hideEvent(QHideEvent *e)
00300 {
00301 delete vis;
00302 vis = 0;
00303 emit hidingVisualization();
00304 QWidget::hideEvent(e);
00305 }
00306
00307 void MainVisual::showBanner(const QString &text, int showTime)
00308 {
00309 bannerTimer->start(showTime);
00310 info_widget->showInformation(text);
00311 }
00312
00313 void MainVisual::showBanner(Metadata *metadata, bool fullScreen, int visMode, int showTime)
00314 {
00315 bannerTimer->start(showTime);
00316 info_widget->showMetadata(metadata, fullScreen, visMode);
00317 }
00318
00319 void MainVisual::hideBanner(void)
00320 {
00321 bannerTimer->stop();
00322 info_widget->showInformation("");
00323 }
00324
00325 void MainVisual::bannerTimeout(void)
00326 {
00327 hideBanner();
00328 }
00329
00330
00331 QStringList MainVisual::Visualizations()
00332 {
00333 QStringList visualizations;
00334 for (const VisFactory* pVisFactory = VisFactory::VisFactories();
00335 pVisFactory; pVisFactory = pVisFactory->next())
00336 {
00337 pVisFactory->plugins(&visualizations);
00338 }
00339
00340 return visualizations;
00341 }
00342
00343 InfoWidget::InfoWidget(QWidget *parent)
00344 : QWidget( parent)
00345 {
00346 hide();
00347 }
00348
00349 void InfoWidget::showMetadata(Metadata *mdata, bool fullScreen, int visMode)
00350 {
00351 if (!mdata)
00352 return;
00353
00354 QString text = "\"" + mdata->Title() + "\"\n" + mdata->Artist() + "\n" + mdata->Album();
00355 QImage albumArt = mdata->getAlbumArt();
00356
00357 if (text == info)
00358 return;
00359
00360 info = text;
00361 if (info.isEmpty())
00362 {
00363 hide();
00364 return;
00365 }
00366
00367
00368 if (visMode != 2 && !fullScreen)
00369 {
00370 hide();
00371 return;
00372 }
00373
00374
00375 if (visMode != 2 && fullScreen && albumArt.isNull())
00376 {
00377 hide();
00378 return;
00379 }
00380
00381 if (fullScreen && ! albumArt.isNull())
00382 {
00383 resize(parentWidget()->width(), parentWidget()->height());
00384 move(0, 0);
00385 }
00386 else
00387 {
00388 resize(displayRect.width(), displayRect.height());
00389 move(displayRect.x(), displayRect.y());
00390 }
00391
00392 info_pixmap = QPixmap(width(), height());
00393 QPainter p(&info_pixmap);
00394
00395 int indent = int(info_pixmap.width() * 0.02);
00396
00397 p.setFont(gContext->GetMediumFont());
00398
00399 QFontMetrics fm(p.font());
00400 int textWidth = fm.width(info);
00401 int textHeight = fm.height() * (info.contains("\n") + 1);
00402 int x = indent;
00403 int y = indent;
00404
00405 if (fullScreen && ! albumArt.isNull())
00406 {
00407 p.fillRect(0, 0, info_pixmap.width(), info_pixmap.height(), QColor ("black"));
00408
00409
00410 QImage image(albumArt);
00411 image = image.smoothScale(width(), height(), QImage::ScaleMin);
00412 p.drawImage(QPoint(width() / 2 - image.width() / 2, height() / 2 - image.height() / 2), image);
00413
00414 x += displayRect.x();
00415 y += displayRect.y();
00416
00417 if (visMode == 2)
00418 p.fillRect(displayRect, QColor ("darkblue"));
00419 }
00420 else
00421 {
00422 p.fillRect(0, 0, info_pixmap.width(), info_pixmap.height(), QColor ("darkblue"));
00423
00424 if (! albumArt.isNull())
00425 {
00426
00427
00428 QImage image(albumArt);
00429 image = image.smoothScale(height(), height(), QImage::ScaleMin);
00430 p.drawImage(QPoint(0, 0), image);
00431 x += height();
00432 }
00433 }
00434
00435
00436 if (!fullScreen || visMode == 2)
00437 {
00438 QString info_copy = info;
00439 for (int offset = 0; offset < textHeight; offset += fm.height())
00440 {
00441 QString l = info_copy.left(info_copy.find("\n"));
00442 p.setPen(Qt::black);
00443 p.drawText(x + 2, y + offset + 2, textWidth, textHeight, Qt::AlignLeft, l);
00444 p.setPen(Qt::white);
00445 p.drawText(x, y + offset, textWidth, textHeight, Qt::AlignLeft, l);
00446 info_copy.remove(0, l.length () + 1);
00447 }
00448 }
00449
00450 show();
00451 repaint();
00452 }
00453
00454 void InfoWidget::showInformation(const QString &text)
00455 {
00456 if (text == info)
00457 return;
00458
00459 info = text;
00460 if (info.isEmpty())
00461 {
00462 hide();
00463 return;
00464 }
00465
00466 resize(displayRect.width(), displayRect.height());
00467 move(displayRect.x(), displayRect.y());
00468
00469 info_pixmap = QPixmap(width(), height());
00470 QPainter p(&info_pixmap);
00471
00472 int indent = int(info_pixmap.width() * 0.02);
00473
00474 p.setFont(gContext->GetMediumFont());
00475
00476 QFontMetrics fm(p.font());
00477 int textWidth = fm.width(info);
00478 int textHeight = fm.height() * (info.contains("\n") + 1);
00479 int x = indent;
00480 int y = indent;
00481
00482 p.fillRect(0, 0, info_pixmap.width(), info_pixmap.height(), QColor ("darkblue"));
00483
00484 QString info_copy = info;
00485 for (int offset = 0; offset < textHeight; offset += fm.height())
00486 {
00487 QString l = info_copy.left(info_copy.find("\n"));
00488 p.setPen(Qt::black);
00489 p.drawText(x + 2, y + offset + 2, textWidth, textHeight, Qt::AlignLeft, l);
00490 p.setPen(Qt::white);
00491 p.drawText(x, y + offset, textWidth, textHeight, Qt::AlignLeft, l);
00492 info_copy.remove(0, l.length () + 1);
00493 }
00494
00495 show();
00496 repaint();
00497 }
00498
00499 void InfoWidget::paintEvent( QPaintEvent * )
00500 {
00501 bitBlt(this, 0, 0, &info_pixmap);
00502 }
00503
00504 StereoScope::StereoScope()
00505 {
00506 fps = 45;
00507 rubberband = false;
00508 falloff = 1.0;
00509
00510 startColor = Qt::green;
00511 targetColor = Qt::red;
00512 }
00513
00514 StereoScope::~StereoScope()
00515 {
00516 }
00517
00518 void StereoScope::resize( const QSize &newsize )
00519 {
00520 size = newsize;
00521
00522 uint os = magnitudes.size();
00523 magnitudes.resize( size.width() * 2 );
00524 for ( ; os < magnitudes.size(); os++ )
00525 magnitudes[os] = 0.0;
00526 }
00527
00528 bool StereoScope::process( VisualNode *node )
00529 {
00530 bool allZero = TRUE;
00531 int i;
00532 long s, indexTo;
00533 double *magnitudesp = magnitudes.data();
00534 double valL, valR, tmpL, tmpR;
00535 double index, step = 512.0 / size.width();
00536
00537 if (node) {
00538 index = 0;
00539 for ( i = 0; i < size.width(); i++) {
00540 indexTo = (int)(index + step);
00541 if (indexTo == (int)(index))
00542 indexTo = (int)(index + 1);
00543
00544 if ( rubberband ) {
00545 valL = magnitudesp[ i ];
00546 valR = magnitudesp[ i + size.width() ];
00547 if (valL < 0.) {
00548 valL += falloff;
00549 if ( valL > 0. )
00550 valL = 0.;
00551 } else {
00552 valL -= falloff;
00553 if ( valL < 0. )
00554 valL = 0.;
00555 }
00556 if (valR < 0.) {
00557 valR += falloff;
00558 if ( valR > 0. )
00559 valR = 0.;
00560 } else {
00561 valR -= falloff;
00562 if ( valR < 0. )
00563 valR = 0.;
00564 }
00565 } else
00566 valL = valR = 0.;
00567
00568 for (s = (int)index; s < indexTo && s < node->length; s++) {
00569 tmpL = ( ( node->left ?
00570 double( node->left[s] ) : 0.) *
00571 double( size.height() / 4 ) ) / 32768.;
00572 tmpR = ( ( node->right ?
00573 double( node->right[s]) : 0.) *
00574 double( size.height() / 4 ) ) / 32768.;
00575 if (tmpL > 0)
00576 valL = (tmpL > valL) ? tmpL : valL;
00577 else
00578 valL = (tmpL < valL) ? tmpL : valL;
00579 if (tmpR > 0)
00580 valR = (tmpR > valR) ? tmpR : valR;
00581 else
00582 valR = (tmpR < valR) ? tmpR : valR;
00583 }
00584
00585 if (valL != 0. || valR != 0.)
00586 allZero = FALSE;
00587
00588 magnitudesp[ i ] = valL;
00589 magnitudesp[ i + size.width() ] = valR;
00590
00591 index = index + step;
00592 }
00593 } else if (rubberband) {
00594 for ( i = 0; i < size.width(); i++) {
00595 valL = magnitudesp[ i ];
00596 if (valL < 0) {
00597 valL += 2;
00598 if (valL > 0.)
00599 valL = 0.;
00600 } else {
00601 valL -= 2;
00602 if (valL < 0.)
00603 valL = 0.;
00604 }
00605
00606 valR = magnitudesp[ i + size.width() ];
00607 if (valR < 0.) {
00608 valR += falloff;
00609 if (valR > 0.)
00610 valR = 0.;
00611 } else {
00612 valR -= falloff;
00613 if (valR < 0.)
00614 valR = 0.;
00615 }
00616
00617 if (valL != 0. || valR != 0.)
00618 allZero = FALSE;
00619
00620 magnitudesp[ i ] = valL;
00621 magnitudesp[ i + size.width() ] = valR;
00622 }
00623 } else {
00624 for ( i = 0; (unsigned) i < magnitudes.size(); i++ )
00625 magnitudesp[ i ] = 0.;
00626 }
00627
00628 return allZero;
00629 }
00630
00631 bool StereoScope::draw( QPainter *p, const QColor &back )
00632 {
00633 double *magnitudesp = magnitudes.data();
00634 double r, g, b, per;
00635
00636 p->fillRect(0, 0, size.width(), size.height(), back);
00637 for ( int i = 1; i < size.width(); i++ ) {
00638
00639 per = double( magnitudesp[ i ] * 2 ) /
00640 double( size.height() / 4 );
00641 if (per < 0.0)
00642 per = -per;
00643 if (per > 1.0)
00644 per = 1.0;
00645 else if (per < 0.0)
00646 per = 0.0;
00647
00648 r = startColor.red() + (targetColor.red() -
00649 startColor.red()) * (per * per);
00650 g = startColor.green() + (targetColor.green() -
00651 startColor.green()) * (per * per);
00652 b = startColor.blue() + (targetColor.blue() -
00653 startColor.blue()) * (per * per);
00654
00655 if (r > 255.0)
00656 r = 255.0;
00657 else if (r < 0.0)
00658 r = 0;
00659
00660 if (g > 255.0)
00661 g = 255.0;
00662 else if (g < 0.0)
00663 g = 0;
00664
00665 if (b > 255.0)
00666 b = 255.0;
00667 else if (b < 0.0)
00668 b = 0;
00669
00670 p->setPen( QColor( int(r), int(g), int(b) ) );
00671 p->setPen(Qt::red);
00672 p->drawLine( i - 1, (int)((size.height() / 4) + magnitudesp[i - 1]),
00673 i, (int)((size.height() / 4) + magnitudesp[i]));
00674
00675
00676 per = double( magnitudesp[ i + size.width() ] * 2 ) /
00677 double( size.height() / 4 );
00678 if (per < 0.0)
00679 per = -per;
00680 if (per > 1.0)
00681 per = 1.0;
00682 else if (per < 0.0)
00683 per = 0.0;
00684
00685 r = startColor.red() + (targetColor.red() -
00686 startColor.red()) * (per * per);
00687 g = startColor.green() + (targetColor.green() -
00688 startColor.green()) * (per * per);
00689 b = startColor.blue() + (targetColor.blue() -
00690 startColor.blue()) * (per * per);
00691
00692 if (r > 255.0)
00693 r = 255.0;
00694 else if (r < 0.0)
00695 r = 0;
00696
00697 if (g > 255.0)
00698 g = 255.0;
00699 else if (g < 0.0)
00700 g = 0;
00701
00702 if (b > 255.0)
00703 b = 255.0;
00704 else if (b < 0.0)
00705 b = 0;
00706
00707 p->setPen( QColor( int(r), int(g), int(b) ) );
00708 p->setPen(Qt::red);
00709 p->drawLine( i - 1, (int)((size.height() * 3 / 4) +
00710 magnitudesp[i + size.width() - 1]),
00711 i, (int)((size.height() * 3 / 4) +
00712 magnitudesp[i + size.width()]));
00713 }
00714
00715 return true;
00716 }
00717
00718 MonoScope::MonoScope()
00719 {
00720 }
00721
00722 MonoScope::~MonoScope()
00723 {
00724 }
00725
00726 bool MonoScope::process( VisualNode *node )
00727 {
00728 bool allZero = TRUE;
00729 int i;
00730 long s, indexTo;
00731 double *magnitudesp = magnitudes.data();
00732 double val, tmp;
00733
00734 double index, step = 512.0 / size.width();
00735
00736 if (node)
00737 {
00738 index = 0;
00739 for ( i = 0; i < size.width(); i++)
00740 {
00741 indexTo = (int)(index + step);
00742 if (indexTo == (int)index)
00743 indexTo = (int)(index + 1);
00744
00745 if ( rubberband )
00746 {
00747 val = magnitudesp[ i ];
00748 if (val < 0.)
00749 {
00750 val += falloff;
00751 if ( val > 0. )
00752 {
00753 val = 0.;
00754 }
00755 }
00756 else
00757 {
00758 val -= falloff;
00759 if ( val < 0. )
00760 {
00761 val = 0.;
00762 }
00763 }
00764 }
00765 else
00766 {
00767 val = 0.;
00768 }
00769
00770 for (s = (int)index; s < indexTo && s < node->length; s++)
00771 {
00772 tmp = ( double( node->left[s] ) +
00773 (node->right ? double( node->right[s] ) : 0) *
00774 double( size.height() / 2 ) ) / 65536.;
00775 if (tmp > 0)
00776 {
00777 val = (tmp > val) ? tmp : val;
00778 }
00779 else
00780 {
00781 val = (tmp < val) ? tmp : val;
00782 }
00783 }
00784
00785 if ( val != 0. )
00786 {
00787 allZero = FALSE;
00788 }
00789 magnitudesp[ i ] = val;
00790 index = index + step;
00791 }
00792 }
00793 else if (rubberband)
00794 {
00795 for ( i = 0; i < size.width(); i++) {
00796 val = magnitudesp[ i ];
00797 if (val < 0) {
00798 val += 2;
00799 if (val > 0.)
00800 val = 0.;
00801 } else {
00802 val -= 2;
00803 if (val < 0.)
00804 val = 0.;
00805 }
00806
00807 if ( val != 0. )
00808 allZero = FALSE;
00809 magnitudesp[ i ] = val;
00810 }
00811 }
00812 else
00813 {
00814 for ( i = 0; i < size.width(); i++ )
00815 magnitudesp[ i ] = 0.;
00816 }
00817
00818 return allZero;
00819 }
00820
00821 bool MonoScope::draw( QPainter *p, const QColor &back )
00822 {
00823 double *magnitudesp = magnitudes.data();
00824 double r, g, b, per;
00825
00826 p->fillRect( 0, 0, size.width(), size.height(), back );
00827 for ( int i = 1; i < size.width(); i++ ) {
00828 per = double( magnitudesp[ i ] ) /
00829 double( size.height() / 4 );
00830 if (per < 0.0)
00831 per = -per;
00832 if (per > 1.0)
00833 per = 1.0;
00834 else if (per < 0.0)
00835 per = 0.0;
00836
00837 r = startColor.red() + (targetColor.red() -
00838 startColor.red()) * (per * per);
00839 g = startColor.green() + (targetColor.green() -
00840 startColor.green()) * (per * per);
00841 b = startColor.blue() + (targetColor.blue() -
00842 startColor.blue()) * (per * per);
00843
00844 if (r > 255.0)
00845 r = 255.0;
00846 else if (r < 0.0)
00847 r = 0;
00848
00849 if (g > 255.0)
00850 g = 255.0;
00851 else if (g < 0.0)
00852 g = 0;
00853
00854 if (b > 255.0)
00855 b = 255.0;
00856 else if (b < 0.0)
00857 b = 0;
00858
00859 p->setPen(Qt::red);
00860
00861 p->drawLine( i - 1, (int)(size.height() / 2 + magnitudesp[ i - 1 ]),
00862 i, (int)(size.height() / 2 + magnitudesp[ i ] ));
00863 }
00864
00865 return true;
00866 }
00867
00868 static class StereoScopeFactory : public VisFactory
00869 {
00870 public:
00871 const QString &name(void) const
00872 {
00873 static QString name("StereoScope");
00874 return name;
00875 }
00876
00877 uint plugins(QStringList *list) const
00878 {
00879 *list << name();
00880 return 1;
00881 }
00882
00883 VisualBase *create(MainVisual *parent, long int winid, const QString &pluginName) const
00884 {
00885 (void)parent;
00886 (void)winid;
00887 (void)pluginName;
00888 return new StereoScope();
00889 }
00890 }StereoScopeFactory;
00891
00892
00893 static class MonoScopeFactory : public VisFactory
00894 {
00895 public:
00896 const QString &name(void) const
00897 {
00898 static QString name("MonoScope");
00899 return name;
00900 }
00901
00902 uint plugins(QStringList *list) const
00903 {
00904 *list << name();
00905 return 1;
00906 }
00907
00908 VisualBase *create(MainVisual *parent, long int winid, const QString &pluginName) const
00909 {
00910 (void)parent;
00911 (void)winid;
00912 (void)pluginName;
00913 return new MonoScope();
00914 }
00915 }MonoScopeFactory;
00916
00917 LogScale::LogScale(int maxscale, int maxrange)
00918 : indices(0), s(0), r(0)
00919 {
00920 setMax(maxscale, maxrange);
00921 }
00922
00923
00924 LogScale::~LogScale()
00925 {
00926 if (indices)
00927 delete [] indices;
00928 }
00929
00930
00931 void LogScale::setMax(int maxscale, int maxrange)
00932 {
00933 if (maxscale == 0 || maxrange == 0)
00934 return;
00935
00936 s = maxscale;
00937 r = maxrange;
00938
00939 if (indices)
00940 delete [] indices;
00941
00942 double alpha;
00943 int i, scaled;
00944 long double domain = (long double) maxscale;
00945 long double range = (long double) maxrange;
00946 long double x = 1.0;
00947 long double dx = 1.0;
00948 long double y = 0.0;
00949 long double yy = 0.0;
00950 long double t = 0.0;
00951 long double e4 = 1.0E-8;
00952
00953 indices = new int[maxrange];
00954 for (i = 0; i < maxrange; i++)
00955 indices[i] = 0;
00956
00957
00958 for (uint i=0; i<10000 && (std::abs(dx) > e4); i++)
00959 {
00960 t = std::log((domain + x) / x);
00961 y = (x * t) - range;
00962 yy = t - (domain / (x + domain));
00963 dx = y / yy;
00964 x -= dx;
00965 }
00966
00967 alpha = x;
00968 for (i = 1; i < (int) domain; i++)
00969 {
00970 scaled = (int) floor(0.5 + (alpha * log((double(i) + alpha) / alpha)));
00971 if (scaled < 1)
00972 scaled = 1;
00973 if (indices[scaled - 1] < i)
00974 indices[scaled - 1] = i;
00975 }
00976 }
00977
00978
00979 int LogScale::operator[](int index)
00980 {
00981 return indices[index];
00982 }
00983