aboutsummaryrefslogtreecommitdiff
path: root/src/plugins/Visual/analyzer
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/Visual/analyzer')
-rw-r--r--src/plugins/Visual/analyzer/CMakeLists.txt70
-rw-r--r--src/plugins/Visual/analyzer/analyzer.cpp308
-rw-r--r--src/plugins/Visual/analyzer/analyzer.h102
-rw-r--r--src/plugins/Visual/analyzer/analyzer.pro35
-rw-r--r--src/plugins/Visual/analyzer/colorwidget.cpp56
-rw-r--r--src/plugins/Visual/analyzer/colorwidget.h50
-rw-r--r--src/plugins/Visual/analyzer/fft.c296
-rw-r--r--src/plugins/Visual/analyzer/fft.h45
-rw-r--r--src/plugins/Visual/analyzer/inlines.h505
-rw-r--r--src/plugins/Visual/analyzer/settingsdialog.cpp62
-rw-r--r--src/plugins/Visual/analyzer/settingsdialog.h46
-rw-r--r--src/plugins/Visual/analyzer/settingsdialog.ui403
-rw-r--r--src/plugins/Visual/analyzer/visualanalyzerfactory.cpp57
-rw-r--r--src/plugins/Visual/analyzer/visualanalyzerfactory.h46
14 files changed, 2081 insertions, 0 deletions
diff --git a/src/plugins/Visual/analyzer/CMakeLists.txt b/src/plugins/Visual/analyzer/CMakeLists.txt
new file mode 100644
index 000000000..7de2ca687
--- /dev/null
+++ b/src/plugins/Visual/analyzer/CMakeLists.txt
@@ -0,0 +1,70 @@
+project(libanalyzer)
+
+cmake_minimum_required(VERSION 2.4.0)
+
+
+
+INCLUDE(FindQt4)
+
+find_package(Qt4 REQUIRED) # find and setup Qt4 for this project
+include(${QT_USE_FILE})
+
+# qt plugin
+ADD_DEFINITIONS( -Wall )
+ADD_DEFINITIONS(${QT_DEFINITIONS})
+ADD_DEFINITIONS(-DQT_PLUGIN)
+ADD_DEFINITIONS(-DQT_NO_DEBUG)
+ADD_DEFINITIONS(-DQT_SHARED)
+ADD_DEFINITIONS(-DQT_THREAD)
+
+include_directories(${CMAKE_CURRENT_BINARY_DIR})
+
+SET(QT_INCLUDES
+ ${QT_INCLUDES}
+ ${CMAKE_CURRENT_BINARY_DIR}/../../../
+)
+
+# libqmmp
+include_directories(${CMAKE_CURRENT_BINARY_DIR}/../../../)
+link_directories(${CMAKE_CURRENT_BINARY_DIR}/../../../)
+
+SET(libanalyzer_SRCS
+ analyzer.cpp
+ colorwidget.cpp
+ settingsdialog.cpp
+ visualanalyzerfactory.cpp
+ fft.c
+)
+
+SET(libanalyzer_MOC_HDRS
+ analyzer.h
+ colorwidget.h
+ fft.h
+ inlines.h
+ settingsdialog.h
+ visualanalyzerfactory.h
+)
+
+#SET(libanalyzer_RCCS translations/translations.qrc)
+
+#QT4_ADD_RESOURCES(libanalyzer_RCC_SRCS ${libanalyzer_RCCS})
+
+QT4_WRAP_CPP(libanalyzer_MOC_SRCS ${libanalyzer_MOC_HDRS})
+
+# user interface
+
+
+SET(libanalyzer_UIS
+ settingsdialog.ui
+)
+
+QT4_WRAP_UI(libanalyzer_UIS_H ${libanalyzer_UIS})
+# Don't forget to include output directory, otherwise
+# the UI file won't be wrapped!
+include_directories(${CMAKE_CURRENT_BINARY_DIR})
+
+ADD_LIBRARY(analyzer SHARED ${libanalyzer_SRCS} ${libanalyzer_MOC_SRCS} ${libanalyzer_UIS_H}
+ ${libanalyzer_RCC_SRCS})
+target_link_libraries(analyzer ${QT_LIBRARIES} -lqmmp)
+install(TARGETS analyzer DESTINATION ${LIB_DIR}/qmmp/Visual PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_EXECUTE GROUP_READ WORLD_EXECUTE WORLD_READ)
+
diff --git a/src/plugins/Visual/analyzer/analyzer.cpp b/src/plugins/Visual/analyzer/analyzer.cpp
new file mode 100644
index 000000000..efcb8b7d7
--- /dev/null
+++ b/src/plugins/Visual/analyzer/analyzer.cpp
@@ -0,0 +1,308 @@
+/***************************************************************************
+ * Copyright (C) 2007 by Ilya Kotov *
+ * forkotov02@hotmail.ru *
+ * *
+ * 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. *
+ * *
+ * 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., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+#include <QTimer>
+#include <QSettings>
+#include <QPainter>
+#include <QMenu>
+#include <QActionGroup>
+
+#include <buffer.h>
+#include <constants.h>
+#include <output.h>
+#include <math.h>
+#include <stdlib.h>
+
+//#include "skin.h"
+#include "fft.h"
+#include "inlines.h"
+#include "analyzer.h"
+
+
+Analyzer::Analyzer (QWidget *parent)
+ : Visual (parent), m_fps ( 20 )
+{
+ QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat);
+ restoreGeometry(settings.value("Analyzer/geometry").toByteArray());
+ setFixedSize(2*300-30,105);
+ m_pixmap = QPixmap (75,20);
+ m_timer = new QTimer (this);
+ connect(m_timer, SIGNAL (timeout()), this, SLOT (timeout()));
+ m_nodes.clear();
+
+ clear();
+ setWindowTitle (tr("Qmmp Analyzer"));
+
+ double peaks_speed[] = { 0.05, 0.1, 0.2, 0.4, 0.8 };
+ double analyzer_speed[] = { 1.2, 1.8, 2.2, 2.8, 2.4 };
+ int intervals[] = { 20 , 40 , 100 , 200 };
+
+ m_peaks_falloff =
+ peaks_speed[settings.value("Analyzer/peaks_falloff", 3).toInt()-1];
+ m_analyzer_falloff =
+ analyzer_speed[settings.value("Analyzer/analyzer_falloff", 3).toInt()-1];
+ m_show_peaks = settings.value("Analyzer/show_peaks", TRUE).toBool();
+ m_timer->setInterval(intervals[settings.value("Analyzer/refresh_rate", 2).toInt() - 1]);
+ m_color1.setNamedColor(settings.value("Analyzer/color1", "Green").toString());
+ m_color2.setNamedColor(settings.value("Analyzer/color2", "Yellow").toString());
+ m_color3.setNamedColor(settings.value("Analyzer/color3", "Red").toString());
+ m_bgColor.setNamedColor(settings.value("Analyzer/bg_color", "Black").toString());
+ m_peakColor.setNamedColor(settings.value("Analyzer/peak_color", "Cyan").toString());
+}
+
+Analyzer::~Analyzer()
+{
+ while (!m_nodes.isEmpty())
+ m_nodes.removeFirst();
+}
+
+void Analyzer::clear()
+{
+ while (!m_nodes.isEmpty())
+ m_nodes.removeFirst();
+ for ( int i = 0; i< 75; ++i )
+ {
+ m_intern_vis_data[i] = 0;
+ m_peaks[i] = 0;
+ }
+ update();
+}
+
+void Analyzer::add ( Buffer *b, unsigned long w, int c, int p )
+{
+ if (!m_timer->isActive ())
+ return;
+ long len = b->nbytes, cnt;
+ short *l = 0, *r = 0;
+
+ len /= c;
+ len /= ( p / 8 );
+ if ( len > 512 )
+ len = 512;
+ cnt = len;
+
+ if ( c == 2 )
+ {
+ l = new short[len];
+ r = new short[len];
+
+ if ( p == 8 )
+ stereo16_from_stereopcm8 ( l, r, b->data, cnt );
+ else if ( p == 16 )
+ stereo16_from_stereopcm16 ( l, r, ( short * ) b->data, cnt );
+ }
+ else if ( c == 1 )
+ {
+ l = new short[len];
+
+ if ( p == 8 )
+ mono16_from_monopcm8 ( l, b->data, cnt );
+ else if ( p == 16 )
+ mono16_from_monopcm16 ( l, ( short * ) b->data, cnt );
+ }
+ else
+ len = 0;
+
+ if (len)
+ m_nodes.append (new VisualNode (l, r, len, w));
+}
+
+void Analyzer::timeout()
+{
+ VisualNode *node = 0;
+
+ if ( /*playing &&*/ output())
+ {
+ //output()->mutex()->lock ();
+ //long olat = output()->latency();
+ //long owrt = output()->written();
+ //output()->mutex()->unlock();
+
+ //long synctime = owrt < olat ? 0 : owrt - olat;
+
+ mutex()->lock ();
+ VisualNode *prev = 0;
+ while ((!m_nodes.isEmpty()))
+ {
+ node = m_nodes.takeFirst();
+ /*if ( node->offset > synctime )
+ break;*/
+
+ if (prev)
+ delete prev;
+ prev = node;
+ }
+ mutex()->unlock();
+ node = prev;
+ }
+
+ if (!node)
+ return;
+ process (node);
+ delete node;
+ update();
+}
+
+void Analyzer::paintEvent (QPaintEvent * e)
+{
+ QPainter painter (this);
+ painter.fillRect(e->rect(),m_bgColor);
+ draw(&painter);
+}
+
+void Analyzer::hideEvent (QHideEvent *)
+{
+ m_timer->stop();
+}
+
+void Analyzer::showEvent (QShowEvent *)
+{
+ m_timer->start();
+}
+
+void Analyzer::closeEvent (QCloseEvent *event)
+{
+ //save geometry
+ QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat);
+ settings.setValue("Analyzer/geometry", saveGeometry());
+ Visual::closeEvent(event); //removes visualization before class deleting
+}
+
+bool Analyzer::process (VisualNode *node)
+{
+ static fft_state *state = 0;
+ if ( !state )
+ state = fft_init();
+
+ short dest_l[256];
+ short dest_r[256];
+
+ const int xscale_short[] =
+ {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 11, 15, 20, 27,
+ 36, 47, 62, 82, 107, 141, 184, 255
+ };
+
+ if ( node )
+ {
+ //i = node->length;
+ calc_freq ( dest_l, node->left );
+ if (node->right)
+ calc_freq ( dest_r, node->right );
+ }
+ else
+ return FALSE;
+ const double y_scale = 3.60673760222; /* 20.0 / log(256) */
+ int yl,yr, j;
+
+ for (int i = 0; i < 19; i++)
+ {
+ yl = yr = 0;
+
+ for ( j = xscale_short[i]; j < xscale_short[i + 1]; j++ )
+ {
+ if ( dest_l[j] > yl )
+ yl = dest_l[j];
+ if ( dest_r[j] > yr && node->right)
+ yr = dest_r[j];
+ }
+ yl >>= 7;
+ int magnitude_l = 0;
+ int magnitude_r = 0;
+ if (node->right)
+ {
+ yr >>= 7;
+ }
+ if (yl)
+ {
+ magnitude_l = int(log (yl) * y_scale);
+ if ( magnitude_l > 15 )
+ magnitude_l = 15;
+ if ( magnitude_l < 0 )
+ magnitude_l = 0;
+ }
+ if (yr && node->right)
+ {
+ magnitude_r = int(log (yr) * y_scale);
+ if ( magnitude_r > 15 )
+ magnitude_r = 15;
+ if ( magnitude_r < 0 )
+ magnitude_r = 0;
+ }
+
+ m_intern_vis_data[i] -= m_analyzer_falloff;
+ m_intern_vis_data[i] = magnitude_l > m_intern_vis_data[i]
+ ? magnitude_l : m_intern_vis_data[i];
+ if (node->right)
+ {
+ m_intern_vis_data[37-i] -= m_analyzer_falloff;
+ m_intern_vis_data[37-i] = magnitude_r > m_intern_vis_data[37-i]
+ ? magnitude_r : m_intern_vis_data[37-i];
+ }
+
+ if (m_show_peaks)
+ {
+ m_peaks[i] -= m_peaks_falloff;
+ m_peaks[i] = magnitude_l > m_peaks[i]
+ ? magnitude_l : m_peaks[i];
+ if (node->right)
+ {
+ m_peaks[37-i] -= m_peaks_falloff;
+ m_peaks[37-i] = magnitude_r > m_peaks[37-i]
+ ? magnitude_r : m_peaks[37-i];
+ }
+ }
+ }
+ return TRUE;
+}
+
+void Analyzer::draw (QPainter *p)
+{
+ QBrush brush(Qt::SolidPattern);
+ for (int j = 0; j < 19; ++j)
+ {
+ for (int i = 0; i <= m_intern_vis_data[j]; ++i)
+ {
+ if (i <= 5)
+ brush.setColor(m_color1);
+ else if (i > 5 && i <= 10)
+ brush.setColor(m_color2);
+ else
+ brush.setColor(m_color3);
+ p->fillRect (j*15+1, height() - i*7, 12, 4, brush);
+ }
+
+ for (int i = 0; i <= m_intern_vis_data[19+j]; ++i)
+ {
+ if (i <= 5)
+ brush.setColor(m_color1);
+ else if (i > 5 && i <= 10)
+ brush.setColor(m_color2);
+ else
+ brush.setColor(m_color3);
+ p->fillRect ((j+19)*15+1, height() - i*7, 12, 4, brush);
+ }
+
+ if (m_show_peaks)
+ {
+ p->fillRect (j*15+1, height() - int(m_peaks[j])*7, 12, 4, m_peakColor);
+ p->fillRect ((j+19)*15+1, height() - int(m_peaks[j+19])*7, 12, 4, m_peakColor);
+ }
+ }
+}
diff --git a/src/plugins/Visual/analyzer/analyzer.h b/src/plugins/Visual/analyzer/analyzer.h
new file mode 100644
index 000000000..ab08d3af0
--- /dev/null
+++ b/src/plugins/Visual/analyzer/analyzer.h
@@ -0,0 +1,102 @@
+/***************************************************************************
+ * Copyright (C) 2007 by Ilya Kotov *
+ * forkotov02@hotmail.ru *
+ * *
+ * 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. *
+ * *
+ * 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., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+#ifndef ANALYZER_H
+#define ANALYZER_H
+
+#include <QWidget>
+#include <QResizeEvent>
+#include <visual.h>
+#include <constants.h>
+#include <QDir>
+
+class QSettings;
+class QTimer;
+class QMenu;
+class QActionGroup;
+
+class Buffer;
+
+
+class VisualNode
+{
+public:
+ VisualNode(short *l, short *r, unsigned long n, unsigned long o)
+ : left(l), right(r), length(n), offset(o)
+ {
+ // left and right are allocated and then passed to this class
+ // the code that allocated left and right should give up all ownership
+ }
+
+ ~VisualNode()
+ {
+ delete [] left;
+ delete [] right;
+ }
+
+ short *left, *right;
+ long length, offset;
+};
+
+class Analyzer : public Visual
+{
+ Q_OBJECT
+
+public:
+ Analyzer( QWidget *parent = 0);
+ virtual ~Analyzer();
+
+ void add(Buffer *, unsigned long, int, int);
+ void clear();
+ void paintEvent( QPaintEvent * );
+
+protected:
+ virtual void hideEvent (QHideEvent *);
+ virtual void showEvent (QShowEvent *);
+ virtual void closeEvent (QCloseEvent *);
+
+public slots:
+ void timeout();
+
+private slots:
+ void updateSettings();
+
+private:
+ bool process(VisualNode *node);
+ void draw(QPainter *p);
+ QPixmap m_pixmap;
+ QPixmap m_bg;
+ QList <VisualNode*> m_nodes;
+ QTimer *m_timer;
+ int m_fps;
+ double m_intern_vis_data[75];
+ double m_peaks[75];
+ double m_peaks_falloff;
+ double m_analyzer_falloff;
+ bool m_show_peaks;
+ //colors
+ QColor m_color1;
+ QColor m_color2;
+ QColor m_color3;
+ QColor m_bgColor;
+ QColor m_peakColor;
+};
+
+
+#endif
diff --git a/src/plugins/Visual/analyzer/analyzer.pro b/src/plugins/Visual/analyzer/analyzer.pro
new file mode 100644
index 000000000..05d95a1ff
--- /dev/null
+++ b/src/plugins/Visual/analyzer/analyzer.pro
@@ -0,0 +1,35 @@
+include(../../plugins.pri)
+
+TARGET=$$PLUGINS_PREFIX/Visual/analyzer
+QMAKE_CLEAN =$$PLUGINS_PREFIX/Visual/libanalyzer.so
+
+
+#FORMS += detailsdialog.ui
+HEADERS += analyzer.h \
+ fft.h \
+ visualanalyzerfactory.h \
+ inlines.h \
+ colorwidget.h \
+ settingsdialog.h
+SOURCES += analyzer.cpp \
+ fft.c \
+ visualanalyzerfactory.cpp \
+ colorwidget.cpp \
+ settingsdialog.cpp
+INCLUDEPATH += ../../../qmmp
+CONFIG += release \
+warn_on \
+plugin
+TEMPLATE = lib
+QMAKE_LIBDIR += ../../../../lib
+LIBS += -lqmmp -L/usr/lib -I/usr/include
+#TRANSLATIONS = translations/ffmpeg_plugin_ru.ts
+#RESOURCES = translations/translations.qrc
+
+isEmpty(LIB_DIR){
+ LIB_DIR = /lib
+}
+target.path = $$LIB_DIR/qmmp/Visual
+INSTALLS += target
+FORMS += settingsdialog.ui
+
diff --git a/src/plugins/Visual/analyzer/colorwidget.cpp b/src/plugins/Visual/analyzer/colorwidget.cpp
new file mode 100644
index 000000000..7117a6cac
--- /dev/null
+++ b/src/plugins/Visual/analyzer/colorwidget.cpp
@@ -0,0 +1,56 @@
+/***************************************************************************
+ * Copyright (C) 2005 by Ilya Kotov *
+ * qmmeter_freedevelop@mail.ru *
+ * *
+ * 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. *
+ * *
+ * 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., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+#include "colorwidget.h"
+
+
+ColorWidget::ColorWidget(QWidget *parent) : QFrame(parent)
+{
+ setFrameShape(QFrame::Box);
+ setAutoFillBackground(TRUE);
+}
+
+
+ColorWidget::~ColorWidget()
+{}
+
+void ColorWidget::mousePressEvent( QMouseEvent *)
+{
+ QColor color = QColorDialog::getColor();
+ if (color.isValid())
+ {
+ QPalette palette;
+ palette.setColor(this->backgroundRole(), color);
+ this->setPalette(palette);
+ }
+}
+
+void ColorWidget::setColor(QString c)
+{
+ QPalette palette;
+ palette.setColor(this->backgroundRole(), c);
+ this->setPalette(palette);
+}
+
+QString ColorWidget::colorName()
+{
+ QPalette palette;
+ palette = this->palette();
+ return (palette.color(this->backgroundRole())).name();
+}
diff --git a/src/plugins/Visual/analyzer/colorwidget.h b/src/plugins/Visual/analyzer/colorwidget.h
new file mode 100644
index 000000000..c145c1035
--- /dev/null
+++ b/src/plugins/Visual/analyzer/colorwidget.h
@@ -0,0 +1,50 @@
+/***************************************************************************
+ * Copyright (C) 2005 by Ilya Kotov *
+ * qmmeter_freedevelop@mail.ru *
+ * *
+ * 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. *
+ * *
+ * 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., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+#ifndef COLORWIDGET_H
+#define COLORWIDGET_H
+
+#include <QFrame>
+#include <QColorDialog>
+#include <QPaintEvent>
+
+/**
+@author user
+*/
+class ColorWidget : public QFrame
+{
+ Q_OBJECT
+public:
+ ColorWidget(QWidget *parent = 0);
+
+ ~ColorWidget();
+
+ QString colorName();
+
+public slots:
+ void setColor (QString);
+
+
+protected:
+ virtual void mousePressEvent ( QMouseEvent *);
+
+
+};
+
+#endif
diff --git a/src/plugins/Visual/analyzer/fft.c b/src/plugins/Visual/analyzer/fft.c
new file mode 100644
index 000000000..7ca1978a5
--- /dev/null
+++ b/src/plugins/Visual/analyzer/fft.c
@@ -0,0 +1,296 @@
+/* fft.c: Iterative implementation of a FFT
+ * Copyright (C) 1999 Richard Boulton <richard@tartarus.org>
+ * Convolution stuff by Ralph Loader <suckfish@ihug.co.nz>
+ *
+ * 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.
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * TODO
+ * Remove compiling in of FFT_BUFFER_SIZE? (Might slow things down, but would
+ * be nice to be able to change size at runtime.)
+ * Finish making / checking thread-safety.
+ * More optimisations.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "fft.h"
+
+//#include <glib.h>
+#include <stdlib.h>
+#include <math.h>
+#ifndef PI
+#ifdef M_PI
+#define PI M_PI
+#else
+#define PI 3.14159265358979323846 /* pi */
+#endif
+#endif
+
+/* ########### */
+/* # Structs # */
+/* ########### */
+
+struct _struct_fft_state {
+ /* Temporary data stores to perform FFT in. */
+ float real[FFT_BUFFER_SIZE];
+ float imag[FFT_BUFFER_SIZE];
+};
+
+/* ############################# */
+/* # Local function prototypes # */
+/* ############################# */
+
+static void fft_prepare(const sound_sample * input, float *re, float *im);
+static void fft_calculate(float *re, float *im);
+static void fft_output(const float *re, const float *im, float *output);
+static int reverseBits(unsigned int initial);
+
+/* #################### */
+/* # Global variables # */
+/* #################### */
+
+/* Table to speed up bit reverse copy */
+static unsigned int bitReverse[FFT_BUFFER_SIZE];
+
+/* The next two tables could be made to use less space in memory, since they
+ * overlap hugely, but hey. */
+static float sintable[FFT_BUFFER_SIZE / 2];
+static float costable[FFT_BUFFER_SIZE / 2];
+
+/* ############################## */
+/* # Externally called routines # */
+/* ############################## */
+
+/* --------- */
+/* FFT stuff */
+/* --------- */
+
+/*
+ * Initialisation routine - sets up tables and space to work in.
+ * Returns a pointer to internal state, to be used when performing calls.
+ * On error, returns NULL.
+ * The pointer should be freed when it is finished with, by fft_close().
+ */
+fft_state *
+fft_init(void)
+{
+ fft_state *state;
+ unsigned int i;
+
+ state = (fft_state *) malloc(sizeof(fft_state));
+ if (!state)
+ return NULL;
+
+ for (i = 0; i < FFT_BUFFER_SIZE; i++) {
+ bitReverse[i] = reverseBits(i);
+ }
+ for (i = 0; i < FFT_BUFFER_SIZE / 2; i++) {
+ float j = 2 * PI * i / FFT_BUFFER_SIZE;
+ costable[i] = cos(j);
+ sintable[i] = sin(j);
+ }
+
+ return state;
+}
+
+/*
+ * Do all the steps of the FFT, taking as input sound data (as described in
+ * sound.h) and returning the intensities of each frequency as floats in the
+ * range 0 to ((FFT_BUFFER_SIZE / 2) * 32768) ^ 2
+ *
+ * FIXME - the above range assumes no frequencies present have an amplitude
+ * larger than that of the sample variation. But this is false: we could have
+ * a wave such that its maximums are always between samples, and it's just
+ * inside the representable range at the places samples get taken.
+ * Question: what _is_ the maximum value possible. Twice that value? Root
+ * two times that value? Hmmm. Think it depends on the frequency, too.
+ *
+ * The input array is assumed to have FFT_BUFFER_SIZE elements,
+ * and the output array is assumed to have (FFT_BUFFER_SIZE / 2 + 1) elements.
+ * state is a (non-NULL) pointer returned by fft_init.
+ */
+void
+fft_perform(const sound_sample * input, float *output, fft_state * state)
+{
+ /* Convert data from sound format to be ready for FFT */
+ fft_prepare(input, state->real, state->imag);
+
+ /* Do the actual FFT */
+ fft_calculate(state->real, state->imag);
+
+ /* Convert the FFT output into intensities */
+ fft_output(state->real, state->imag, output);
+}
+
+/*
+ * Free the state.
+ */
+void
+fft_close(fft_state * state)
+{
+ if (state)
+ free(state);
+}
+
+/* ########################### */
+/* # Locally called routines # */
+/* ########################### */
+
+/*
+ * Prepare data to perform an FFT on
+ */
+static void
+fft_prepare(const sound_sample * input, float *re, float *im)
+{
+ unsigned int i;
+ float *realptr = re;
+ float *imagptr = im;
+
+ /* Get input, in reverse bit order */
+ for (i = 0; i < FFT_BUFFER_SIZE; i++) {
+ *realptr++ = input[bitReverse[i]];
+ *imagptr++ = 0;
+ }
+}
+
+/*
+ * Take result of an FFT and calculate the intensities of each frequency
+ * Note: only produces half as many data points as the input had.
+ * This is roughly a consequence of the Nyquist sampling theorm thingy.
+ * (FIXME - make this comment better, and helpful.)
+ *
+ * The two divisions by 4 are also a consequence of this: the contributions
+ * returned for each frequency are split into two parts, one at i in the
+ * table, and the other at FFT_BUFFER_SIZE - i, except for i = 0 and
+ * FFT_BUFFER_SIZE which would otherwise get float (and then 4* when squared)
+ * the contributions.
+ */
+static void
+fft_output(const float *re, const float *im, float *output)
+{
+ float *outputptr = output;
+ const float *realptr = re;
+ const float *imagptr = im;
+ float *endptr = output + FFT_BUFFER_SIZE / 2;
+
+#ifdef DEBUG
+ unsigned int i, j;
+#endif
+
+ while (outputptr <= endptr) {
+ *outputptr = (*realptr * *realptr) + (*imagptr * *imagptr);
+ outputptr++;
+ realptr++;
+ imagptr++;
+ }
+ /* Do divisions to keep the constant and highest frequency terms in scale
+ * with the other terms. */
+ *output /= 4;
+ *endptr /= 4;
+
+#ifdef DEBUG
+ printf("Recalculated input:\n");
+ for (i = 0; i < FFT_BUFFER_SIZE; i++) {
+ float val_real = 0;
+ float val_imag = 0;
+ for (j = 0; j < FFT_BUFFER_SIZE; j++) {
+ float fact_real = cos(-2 * j * i * PI / FFT_BUFFER_SIZE);
+ float fact_imag = sin(-2 * j * i * PI / FFT_BUFFER_SIZE);
+ val_real += fact_real * re[j] - fact_imag * im[j];
+ val_imag += fact_real * im[j] + fact_imag * re[j];
+ }
+ printf("%5d = %8f + i * %8f\n", i,
+ val_real / FFT_BUFFER_SIZE, val_imag / FFT_BUFFER_SIZE);
+ }
+ printf("\n");
+#endif
+}
+
+/*
+ * Actually perform the FFT
+ */
+static void
+fft_calculate(float *re, float *im)
+{
+ unsigned int i, j, k;
+ unsigned int exchanges;
+ float fact_real, fact_imag;
+ float tmp_real, tmp_imag;
+ unsigned int factfact;
+
+ /* Set up some variables to reduce calculation in the loops */
+ exchanges = 1;
+ factfact = FFT_BUFFER_SIZE / 2;
+
+ /* Loop through the divide and conquer steps */
+ for (i = FFT_BUFFER_SIZE_LOG; i != 0; i--) {
+ /* In this step, we have 2 ^ (i - 1) exchange groups, each with
+ * 2 ^ (FFT_BUFFER_SIZE_LOG - i) exchanges
+ */
+ /* Loop through the exchanges in a group */
+ for (j = 0; j != exchanges; j++) {
+ /* Work out factor for this exchange
+ * factor ^ (exchanges) = -1
+ * So, real = cos(j * PI / exchanges),
+ * imag = sin(j * PI / exchanges)
+ */
+ fact_real = costable[j * factfact];
+ fact_imag = sintable[j * factfact];
+
+ /* Loop through all the exchange groups */
+ for (k = j; k < FFT_BUFFER_SIZE; k += exchanges << 1) {
+ int k1 = k + exchanges;
+ /* newval[k] := val[k] + factor * val[k1]
+ * newval[k1] := val[k] - factor * val[k1]
+ **/
+#ifdef DEBUG
+ printf("%d %d %d\n", i, j, k);
+ printf("Exchange %d with %d\n", k, k1);
+ printf("Factor %9f + i * %8f\n", fact_real, fact_imag);
+#endif
+ /* FIXME - potential scope for more optimization here? */
+ tmp_real = fact_real * re[k1] - fact_imag * im[k1];
+ tmp_imag = fact_real * im[k1] + fact_imag * re[k1];
+ re[k1] = re[k] - tmp_real;
+ im[k1] = im[k] - tmp_imag;
+ re[k] += tmp_real;
+ im[k] += tmp_imag;
+#ifdef DEBUG
+ for (k1 = 0; k1 < FFT_BUFFER_SIZE; k1++) {
+ printf("%5d = %8f + i * %8f\n", k1, real[k1], imag[k1]);
+ }
+#endif
+ }
+ }
+ exchanges <<= 1;
+ factfact >>= 1;
+ }
+}
+
+static int
+reverseBits(unsigned int initial)
+{
+ unsigned int reversed = 0, loop;
+ for (loop = 0; loop < FFT_BUFFER_SIZE_LOG; loop++) {
+ reversed <<= 1;
+ reversed += (initial & 1);
+ initial >>= 1;
+ }
+ return reversed;
+}
diff --git a/src/plugins/Visual/analyzer/fft.h b/src/plugins/Visual/analyzer/fft.h
new file mode 100644
index 000000000..431afa365
--- /dev/null
+++ b/src/plugins/Visual/analyzer/fft.h
@@ -0,0 +1,45 @@
+/* fft.h: Header for iterative implementation of a FFT
+ * Copyright (C) 1999 Richard Boulton <richard@tartarus.org>
+ *
+ * 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.
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _FFT_H_
+#define _FFT_H_
+
+#define FFT_BUFFER_SIZE_LOG 9
+
+#define FFT_BUFFER_SIZE (1 << FFT_BUFFER_SIZE_LOG)
+
+/* sound sample - should be an signed 16 bit value */
+typedef short int sound_sample;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* FFT library */
+ typedef struct _struct_fft_state fft_state;
+ fft_state *fft_init(void);
+ void fft_perform(const sound_sample * input, float *output,
+ fft_state * state);
+ void fft_close(fft_state * state);
+
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _FFT_H_ */
diff --git a/src/plugins/Visual/analyzer/inlines.h b/src/plugins/Visual/analyzer/inlines.h
new file mode 100644
index 000000000..3efccf0de
--- /dev/null
+++ b/src/plugins/Visual/analyzer/inlines.h
@@ -0,0 +1,505 @@
+// Copyright (c) 2000-2001 Brad Hughes <bhughes@trolltech.com>
+//
+// Use, modification and distribution is allowed without limitation,
+// warranty, or liability of any kind.
+//
+
+#ifndef INLINES_H
+#define INLINES_H
+
+#include "fft.h"
+
+// *fast* convenience functions
+static inline void
+calc_freq(short* dest, short *src)
+{
+ static fft_state *state = NULL;
+ float tmp_out[257];
+ int i;
+
+ if (!state)
+ state = fft_init();
+
+ fft_perform(src, tmp_out, state);
+
+ for (i = 0; i < 256; i++)
+ dest[i] = ((int) sqrt(tmp_out[i + 1])) >> 8;
+}
+
+static inline void
+calc_mono_freq(short dest[2][256], short src[2][512], int nch)
+{
+ int i;
+ short *d, *sl, *sr, tmp[512];
+
+ if (nch == 1)
+ calc_freq(dest[0], src[0]);
+ else
+ {
+ d = tmp;
+ sl = src[0];
+ sr = src[1];
+ for (i = 0; i < 512; i++)
+ {
+ *(d++) = (*(sl++) + *(sr++)) >> 1;
+ }
+ calc_freq(dest[0], tmp);
+ }
+}
+
+static inline void stereo16_from_stereopcm8(register short *l,
+ register short *r,
+ register uchar *c,
+ long cnt)
+{
+ while (cnt >= 4l)
+ {
+ l[0] = c[0];
+ r[0] = c[1];
+ l[1] = c[2];
+ r[1] = c[3];
+ l[2] = c[4];
+ r[2] = c[5];
+ l[3] = c[6];
+ r[3] = c[7];
+ l += 4;
+ r += 4;
+ c += 8;
+ cnt -= 4l;
+ }
+
+ if (cnt > 0l)
+ {
+ l[0] = c[0];
+ r[0] = c[1];
+ if (cnt > 1l)
+ {
+ l[1] = c[2];
+ r[1] = c[3];
+ if (cnt > 2l)
+ {
+ l[2] = c[4];
+ r[2] = c[5];
+ }
+ }
+ }
+}
+
+
+static inline void stereo16_from_stereopcm16(register short *l,
+ register short *r,
+ register short *s,
+ long cnt)
+{
+ while (cnt >= 4l)
+ {
+ l[0] = s[0];
+ r[0] = s[1];
+ l[1] = s[2];
+ r[1] = s[3];
+ l[2] = s[4];
+ r[2] = s[5];
+ l[3] = s[6];
+ r[3] = s[7];
+ l += 4;
+ r += 4;
+ s += 8;
+ cnt -= 4l;
+ }
+
+ if (cnt > 0l)
+ {
+ l[0] = s[0];
+ r[0] = s[1];
+ if (cnt > 1l)
+ {
+ l[1] = s[2];
+ r[1] = s[3];
+ if (cnt > 2l)
+ {
+ l[2] = s[4];
+ r[2] = s[5];
+ }
+ }
+ }
+}
+
+
+static inline void mono16_from_monopcm8(register short *l,
+ register uchar *c,
+ long cnt)
+{
+ while (cnt >= 4l)
+ {
+ l[0] = c[0];
+ l[1] = c[1];
+ l[2] = c[2];
+ l[3] = c[3];
+ l += 4;
+ c += 4;
+ cnt -= 4l;
+ }
+
+ if (cnt > 0l)
+ {
+ l[0] = c[0];
+ if (cnt > 1l)
+ {
+ l[1] = c[1];
+ if (cnt > 2l)
+ {
+ l[2] = c[2];
+ }
+ }
+ }
+}
+
+
+static inline void mono16_from_monopcm16(register short *l,
+ register short *s,
+ long cnt)
+{
+ while (cnt >= 4l)
+ {
+ l[0] = s[0];
+ l[1] = s[1];
+ l[2] = s[2];
+ l[3] = s[3];
+ l += 4;
+ s += 4;
+ cnt -= 4l;
+ }
+
+ if (cnt > 0l)
+ {
+ l[0] = s[0];
+ if (cnt > 1l)
+ {
+ l[1] = s[1];
+ if (cnt > 2l)
+ {
+ l[2] = s[2];
+ }
+ }
+ }
+}
+
+
+static inline void fast_short_set(register short *p,
+ short v,
+ long c)
+{
+ while (c >= 4l)
+ {
+ p[0] = v;
+ p[1] = v;
+ p[2] = v;
+ p[3] = v;
+ p += 4;
+ c -= 4l;
+ }
+
+ if (c > 0l)
+ {
+ p[0] = v;
+ if (c > 1l)
+ {
+ p[1] = v;
+ if (c > 2l)
+ {
+ p[2] = v;
+ }
+ }
+ }
+}
+
+#ifdef FFTW
+static inline void fast_real_set(register fftw_real *p,
+ fftw_real v,
+ long c)
+{
+ while (c >= 4l)
+ {
+ p[0] = v;
+ p[1] = v;
+ p[2] = v;
+ p[3] = v;
+ p += 4;
+ c -= 4l;
+ }
+
+ if (c > 0l)
+ {
+ p[0] = v;
+ if (c > 1l)
+ {
+ p[1] = v;
+ if (c > 2l)
+ {
+ p[2] = v;
+ }
+ }
+ }
+}
+
+static inline void fast_complex_set(register fftw_complex *p,
+ fftw_complex v,
+ long c)
+{
+ while (c >= 4l)
+ {
+ p[0] = v;
+ p[1] = v;
+ p[2] = v;
+ p[3] = v;
+ p += 4;
+ c -= 4l;
+ }
+
+ if (c > 0l)
+ {
+ p[0] = v;
+ if (c > 1l)
+ {
+ p[1] = v;
+ if (c > 2l)
+ {
+ p[2] = v;
+ }
+ }
+ }
+}
+
+
+static inline void fast_real_set_from_short(register fftw_real *d,
+ register short *s,
+ long c)
+{
+ while (c >= 4l)
+ {
+ d[0] = fftw_real(s[0]);
+ d[1] = fftw_real(s[1]);
+ d[2] = fftw_real(s[2]);
+ d[3] = fftw_real(s[3]);
+ d += 4;
+ s += 4;
+ c -= 4l;
+ }
+
+ if (c > 0l)
+ {
+ d[0] = fftw_real(s[0]);
+ if (c > 1l)
+ {
+ d[1] = fftw_real(s[1]);
+ if (c > 2l)
+ {
+ d[2] = fftw_real(s[2]);
+ }
+ }
+ }
+}
+
+static inline void fast_complex_set_from_short(register fftw_complex *d,
+ register short *s,
+ long c)
+{
+ while (c >= 4l)
+ {
+ d[0].re = fftw_real(s[0]);
+ d[0].im = 0;
+ d[1].re = fftw_real(s[1]);
+ d[1].im = 0;
+ d[2].re = fftw_real(s[2]);
+ d[2].im = 0;
+ d[3].re = fftw_real(s[3]);
+ d[3].im = 0;
+ d += 4;
+ s += 4;
+ c -= 4l;
+ }
+
+ if (c > 0l)
+ {
+ d[0].re = fftw_real(s[0]);
+ d[0].im = 0;
+ if (c > 1l)
+ {
+ d[1].re = fftw_real(s[1]);
+ d[1].im = 0;
+ if (c > 2l)
+ {
+ d[2].re = fftw_real(s[2]);
+ d[2].im = 0;
+ }
+ }
+ }
+}
+
+
+static inline void fast_real_avg_from_shorts(register fftw_real *d,
+ register short *s1,
+ register short *s2,
+ long c)
+{
+ fftw_real t0, t1, t2, t3;
+ while (c >= 4l)
+ {
+ t0 = (s1[0] + s2[0]) / 2;
+ t1 = (s1[1] + s2[1]) / 2;
+ t2 = (s1[2] + s2[2]) / 2;
+ t3 = (s1[3] + s2[3]) / 2;
+ d[0] = t0;
+ d[1] = t1;
+ d[2] = t2;
+ d[3] = t3;
+ d += 4;
+ s1 += 4;
+ s2 += 4;
+ c -= 4l;
+ }
+
+ if (c > 0l)
+ {
+ d[0] = fftw_real((s1[0] + s2[0]) / 2);
+ if (c > 1l)
+ {
+ d[1] = fftw_real((s1[1] + s2[1]) / 2);
+ if (c > 2l)
+ {
+ d[2] = fftw_real((s1[2] + s2[2]) / 2);
+ }
+ }
+ }
+}
+
+static inline void fast_complex_avg_from_shorts(register fftw_complex *d,
+ register short *s1,
+ register short *s2,
+ long c)
+{
+ fftw_real t0, t1, t2, t3;
+ while (c >= 4l)
+ {
+ t0 = (s1[0] + s2[0]) / 2;
+ t1 = (s1[1] + s2[1]) / 2;
+ t2 = (s1[2] + s2[2]) / 2;
+ t3 = (s1[3] + s2[3]) / 2;
+ d[0].re = t0;
+ d[0].im = 0;
+ d[1].re = t1;
+ d[1].im = 0;
+ d[2].re = t2;
+ d[2].im = 0;
+ d[3].re = t3;
+ d[3].im = 0;
+ d += 4;
+ s1 += 4;
+ s2 += 4;
+ c -= 4l;
+ }
+
+ if (c > 0l)
+ {
+ d[0].re = fftw_real((s1[0] + s2[0]) / 2);
+ d[0].im = 0;
+ if (c > 1l)
+ {
+ d[1].re = fftw_real((s1[1] + s2[1]) / 2);
+ d[1].im = 0;
+ if (c > 2l)
+ {
+ d[2].re = fftw_real((s1[2] + s2[2]) / 2);
+ d[2].im = 0;
+ }
+ }
+ }
+}
+
+
+static inline fftw_complex fftw_complex_from_real( fftw_real re )
+{
+ fftw_complex c;
+
+ c.re = re;
+ c.im = 0;
+
+ return c;
+}
+
+static inline void fast_reals_set(register fftw_real *p1,
+ register fftw_real *p2,
+ fftw_real v,
+ long c)
+{
+ while (c >= 4l)
+ {
+ p1[0] = v;
+ p1[1] = v;
+ p1[2] = v;
+ p1[3] = v;
+ p2[0] = v;
+ p2[1] = v;
+ p2[2] = v;
+ p2[3] = v;
+ p1 += 4;
+ p2 += 4;
+ c -= 4l;
+ }
+
+ if (c > 0l)
+ {
+ p1[0] = v;
+ p2[0] = v;
+ if (c > 1l)
+ {
+ p1[1] = v;
+ p2[1] = v;
+ if (c > 2l)
+ {
+ p1[2] = v;
+ p2[2] = v;
+ }
+ }
+ }
+}
+
+static inline void fast_complex_set(register fftw_complex *p1,
+ register fftw_complex *p2,
+ fftw_complex v,
+ long c)
+{
+ while (c >= 4l)
+ {
+ p1[0] = v;
+ p1[1] = v;
+ p1[2] = v;
+ p1[3] = v;
+ p2[0] = v;
+ p2[1] = v;
+ p2[2] = v;
+ p2[3] = v;
+ p1 += 4;
+ p2 += 4;
+ c -= 4l;
+ }
+
+ if (c > 0l)
+ {
+ p1[0] = v;
+ p2[0] = v;
+ if (c > 1l)
+ {
+ p1[1] = v;
+ p2[1] = v;
+ if (c > 2l)
+ {
+ p1[2] = v;
+ p2[2] = v;
+ }
+ }
+ }
+}
+#endif // FFTW
+
+#endif // INLINES_H
diff --git a/src/plugins/Visual/analyzer/settingsdialog.cpp b/src/plugins/Visual/analyzer/settingsdialog.cpp
new file mode 100644
index 000000000..badadc190
--- /dev/null
+++ b/src/plugins/Visual/analyzer/settingsdialog.cpp
@@ -0,0 +1,62 @@
+/***************************************************************************
+ * Copyright (C) 2007 by Ilya Kotov *
+ * forkotov02@hotmail.ru *
+ * *
+ * 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. *
+ * *
+ * 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., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+
+#include <QSettings>
+#include <QDir>
+
+#include "settingsdialog.h"
+
+SettingsDialog::SettingsDialog(QWidget *parent)
+ : QDialog(parent)
+{
+ ui.setupUi(this);
+ setAttribute(Qt::WA_DeleteOnClose, TRUE);
+ QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat);
+ ui.analyzerComboBox->setCurrentIndex(settings.value("Analyzer/analyzer_falloff", 3).toInt()-1);
+ ui.peaksCheckBox->setChecked(settings.value("Analyzer/show_peaks", TRUE).toBool());
+ ui.peaksComboBox->setCurrentIndex(settings.value("Analyzer/peaks_falloff", 3).toInt()-1);
+ ui.fpsComboBox->setCurrentIndex(settings.value("Analyzer/refresh_rate", 2).toInt()-1);
+ ui.colorWidget1->setColor(settings.value("Analyzer/color1", "Green").toString());
+ ui.colorWidget2->setColor(settings.value("Analyzer/color2", "Yellow").toString());
+ ui.colorWidget3->setColor(settings.value("Analyzer/color3", "Red").toString());
+ ui.bgColorWidget->setColor(settings.value("Analyzer/bg_color", "Black").toString());
+ ui.peakColorWidget->setColor(settings.value("Analyzer/peak_color", "Cyan").toString());
+ connect (ui.okButton, SIGNAL(clicked()),SLOT(writeSettings()));
+}
+
+
+SettingsDialog::~SettingsDialog()
+{
+}
+
+void SettingsDialog::writeSettings()
+{
+ QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat);
+ settings.setValue("Analyzer/analyzer_falloff", ui.analyzerComboBox->currentIndex() + 1);
+ settings.setValue("Analyzer/peaks_falloff", ui.peaksComboBox->currentIndex() + 1);
+ settings.setValue("Analyzer/refresh_rate", ui.fpsComboBox->currentIndex() + 1);
+ settings.setValue("Analyzer/show_peaks", ui.peaksCheckBox->isChecked());
+ settings.setValue("Analyzer/color1", ui.colorWidget1->colorName());
+ settings.setValue("Analyzer/color2", ui.colorWidget2->colorName());
+ settings.setValue("Analyzer/color3", ui.colorWidget3->colorName());
+ settings.setValue("Analyzer/bg_color", ui.bgColorWidget->colorName());
+ settings.setValue("Analyzer/peak_color", ui.peakColorWidget->colorName());
+ accept();
+}
diff --git a/src/plugins/Visual/analyzer/settingsdialog.h b/src/plugins/Visual/analyzer/settingsdialog.h
new file mode 100644
index 000000000..b7c466477
--- /dev/null
+++ b/src/plugins/Visual/analyzer/settingsdialog.h
@@ -0,0 +1,46 @@
+/***************************************************************************
+ * Copyright (C) 2007 by Ilya Kotov *
+ * forkotov02@hotmail.ru *
+ * *
+ * 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. *
+ * *
+ * 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., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+#ifndef SETTINGSDIALOG_H
+#define SETTINGSDIALOG_H
+
+#include <QDialog>
+
+#include "ui_settingsdialog.h"
+
+/**
+ @author Ilya Kotov <forkotov02@hotmail.ru>
+*/
+class SettingsDialog : public QDialog
+{
+Q_OBJECT
+public:
+ SettingsDialog(QWidget *parent = 0);
+
+ ~SettingsDialog();
+
+private slots:
+ void writeSettings();
+
+private:
+ Ui::SettingsDialog ui;
+
+};
+
+#endif
diff --git a/src/plugins/Visual/analyzer/settingsdialog.ui b/src/plugins/Visual/analyzer/settingsdialog.ui
new file mode 100644
index 000000000..4ddd391a3
--- /dev/null
+++ b/src/plugins/Visual/analyzer/settingsdialog.ui
@@ -0,0 +1,403 @@
+<ui version="4.0" >
+ <class>SettingsDialog</class>
+ <widget class="QDialog" name="SettingsDialog" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>292</width>
+ <height>327</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Analyzer Plugin Settings</string>
+ </property>
+ <layout class="QGridLayout" >
+ <item row="0" column="0" colspan="3" >
+ <widget class="QGroupBox" name="groupBox_2" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Minimum" hsizetype="Preferred" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title" >
+ <string>General</string>
+ </property>
+ <layout class="QGridLayout" >
+ <item row="0" column="0" >
+ <widget class="QCheckBox" name="peaksCheckBox" >
+ <property name="layoutDirection" >
+ <enum>Qt::LeftToRight</enum>
+ </property>
+ <property name="text" >
+ <string>Show peaks</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0" >
+ <widget class="QLabel" name="label_10" >
+ <property name="text" >
+ <string>Analyzer falloff:</string>
+ </property>
+ <property name="alignment" >
+ <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1" >
+ <widget class="QComboBox" name="analyzerComboBox" >
+ <property name="currentIndex" >
+ <number>2</number>
+ </property>
+ <item>
+ <property name="text" >
+ <string>Slowest</string>
+ </property>
+ </item>
+ <item>
+ <property name="text" >
+ <string>Slow</string>
+ </property>
+ </item>
+ <item>
+ <property name="text" >
+ <string>Medium</string>
+ </property>
+ </item>
+ <item>
+ <property name="text" >
+ <string>Fast</string>
+ </property>
+ </item>
+ <item>
+ <property name="text" >
+ <string>Fastest</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="2" column="0" >
+ <widget class="QLabel" name="label_9" >
+ <property name="text" >
+ <string>Peaks falloff:</string>
+ </property>
+ <property name="alignment" >
+ <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1" >
+ <widget class="QComboBox" name="peaksComboBox" >
+ <property name="currentIndex" >
+ <number>2</number>
+ </property>
+ <item>
+ <property name="text" >
+ <string>Slowest</string>
+ </property>
+ </item>
+ <item>
+ <property name="text" >
+ <string>Slow</string>
+ </property>
+ </item>
+ <item>
+ <property name="text" >
+ <string>Medium</string>
+ </property>
+ </item>
+ <item>
+ <property name="text" >
+ <string>Fast</string>
+ </property>
+ </item>
+ <item>
+ <property name="text" >
+ <string>Fastest</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="3" column="0" >
+ <widget class="QLabel" name="label_11" >
+ <property name="text" >
+ <string>Refresh rate:</string>
+ </property>
+ <property name="alignment" >
+ <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1" >
+ <widget class="QComboBox" name="fpsComboBox" >
+ <property name="currentIndex" >
+ <number>0</number>
+ </property>
+ <item>
+ <property name="text" >
+ <string>50 FPS</string>
+ </property>
+ </item>
+ <item>
+ <property name="text" >
+ <string>25 FPS</string>
+ </property>
+ </item>
+ <item>
+ <property name="text" >
+ <string>10 FPS</string>
+ </property>
+ </item>
+ <item>
+ <property name="text" >
+ <string>5 FPS</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="1" column="0" colspan="3" >
+ <widget class="QGroupBox" name="groupBox" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="MinimumExpanding" hsizetype="Preferred" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title" >
+ <string>Colors</string>
+ </property>
+ <layout class="QGridLayout" >
+ <item row="0" column="0" >
+ <widget class="QLabel" name="label_4" >
+ <property name="text" >
+ <string>Peaks:</string>
+ </property>
+ <property name="alignment" >
+ <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1" >
+ <widget class="ColorWidget" native="1" name="peakColorWidget" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Fixed" hsizetype="Fixed" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize" >
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="2" >
+ <widget class="QLabel" name="label_6" >
+ <property name="text" >
+ <string>Analyzer #1:</string>
+ </property>
+ <property name="alignment" >
+ <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="3" >
+ <widget class="ColorWidget" native="1" name="colorWidget1" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Fixed" hsizetype="Fixed" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize" >
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0" >
+ <widget class="QLabel" name="label_5" >
+ <property name="text" >
+ <string>Background:</string>
+ </property>
+ <property name="alignment" >
+ <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1" >
+ <widget class="ColorWidget" native="1" name="bgColorWidget" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Fixed" hsizetype="Fixed" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize" >
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="2" >
+ <widget class="QLabel" name="label_7" >
+ <property name="text" >
+ <string>Analyzer #2:</string>
+ </property>
+ <property name="alignment" >
+ <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="3" >
+ <widget class="ColorWidget" native="1" name="colorWidget2" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Fixed" hsizetype="Fixed" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize" >
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0" colspan="2" >
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>111</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="2" column="2" >
+ <widget class="QLabel" name="label_8" >
+ <property name="text" >
+ <string>Analyzer #3:</string>
+ </property>
+ <property name="alignment" >
+ <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="3" >
+ <widget class="ColorWidget" native="1" name="colorWidget3" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Fixed" hsizetype="Fixed" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize" >
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="2" column="0" >
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType" >
+ <enum>QSizePolicy::Minimum</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>95</width>
+ <height>29</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="2" column="1" >
+ <widget class="QPushButton" name="okButton" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Expanding" hsizetype="Preferred" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize" >
+ <size>
+ <width>16777215</width>
+ <height>30</height>
+ </size>
+ </property>
+ <property name="text" >
+ <string>&amp;OK</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="2" >
+ <widget class="QPushButton" name="cancelButton" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Minimum" hsizetype="Preferred" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize" >
+ <size>
+ <width>16777215</width>
+ <height>30</height>
+ </size>
+ </property>
+ <property name="text" >
+ <string>&amp;Cancel</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>ColorWidget</class>
+ <extends>QWidget</extends>
+ <header>colorwidget.h</header>
+ <container>1</container>
+ </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>cancelButton</sender>
+ <signal>clicked()</signal>
+ <receiver>SettingsDialog</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>220</x>
+ <y>286</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>276</x>
+ <y>309</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/src/plugins/Visual/analyzer/visualanalyzerfactory.cpp b/src/plugins/Visual/analyzer/visualanalyzerfactory.cpp
new file mode 100644
index 000000000..0e110b2cd
--- /dev/null
+++ b/src/plugins/Visual/analyzer/visualanalyzerfactory.cpp
@@ -0,0 +1,57 @@
+/***************************************************************************
+ * Copyright (C) 2007 by Ilya Kotov *
+ * forkotov02@hotmail.ru *
+ * *
+ * 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. *
+ * *
+ * 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., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+
+#include <QtGui>
+
+#include "settingsdialog.h"
+#include "visualanalyzerfactory.h"
+#include "analyzer.h"
+
+const VisualProperties VisualAnalyzerFactory::properties() const
+{
+ VisualProperties properties;
+ properties.name = tr("Analyzer Plugin");
+ return properties;
+};
+
+Visual *VisualAnalyzerFactory::create(QWidget *parent)
+{
+ return new Analyzer(parent);
+};
+
+void VisualAnalyzerFactory::showSettings(QWidget *parent)
+{
+ SettingsDialog *s = new SettingsDialog(parent);
+ s -> show();
+};
+
+void VisualAnalyzerFactory::showAbout(QWidget *parent)
+{
+ QMessageBox::about (parent, tr("About Analyzer Visual Plugin"),
+ tr("Qmmp Analyzer Visual Plugin")+"\n"+
+ tr("Writen by: Ilya Kotov <forkotov02@hotmail.ru>"));
+};
+
+QTranslator *VisualAnalyzerFactory::createTranslator(QObject *parent)
+{
+ return 0;
+};
+
+Q_EXPORT_PLUGIN(VisualAnalyzerFactory)
diff --git a/src/plugins/Visual/analyzer/visualanalyzerfactory.h b/src/plugins/Visual/analyzer/visualanalyzerfactory.h
new file mode 100644
index 000000000..54f52bfe2
--- /dev/null
+++ b/src/plugins/Visual/analyzer/visualanalyzerfactory.h
@@ -0,0 +1,46 @@
+/***************************************************************************
+ * Copyright (C) 2007 by Ilya Kotov *
+ * forkotov02@hotmail.ru *
+ * *
+ * 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. *
+ * *
+ * 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., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+#ifndef VISUALANALYZERFACTORY_H
+#define VISUALANALYZERFACTORY_H
+
+
+#include <QObject>
+
+#include <visualfactory.h>
+#include <visual.h>
+
+/**
+ @author Ilya Kotov <forkotov02@hotmail.ru>
+*/
+class VisualAnalyzerFactory : public QObject, public VisualFactory
+{
+Q_OBJECT
+Q_INTERFACES(VisualFactory);
+
+public:
+ const VisualProperties properties() const;
+ Visual *create(QWidget *parent);
+ void showSettings(QWidget *parent);
+ void showAbout(QWidget *parent);
+ QTranslator *createTranslator(QObject *parent);
+};
+
+
+#endif