diff options
Diffstat (limited to 'src/plugins/Visual')
| -rw-r--r-- | src/plugins/Visual/CMakeLists.txt | 8 | ||||
| -rw-r--r-- | src/plugins/Visual/Visual.pro | 3 | ||||
| -rw-r--r-- | src/plugins/Visual/analyzer/CMakeLists.txt | 70 | ||||
| -rw-r--r-- | src/plugins/Visual/analyzer/analyzer.cpp | 308 | ||||
| -rw-r--r-- | src/plugins/Visual/analyzer/analyzer.h | 102 | ||||
| -rw-r--r-- | src/plugins/Visual/analyzer/analyzer.pro | 35 | ||||
| -rw-r--r-- | src/plugins/Visual/analyzer/colorwidget.cpp | 56 | ||||
| -rw-r--r-- | src/plugins/Visual/analyzer/colorwidget.h | 50 | ||||
| -rw-r--r-- | src/plugins/Visual/analyzer/fft.c | 296 | ||||
| -rw-r--r-- | src/plugins/Visual/analyzer/fft.h | 45 | ||||
| -rw-r--r-- | src/plugins/Visual/analyzer/inlines.h | 505 | ||||
| -rw-r--r-- | src/plugins/Visual/analyzer/settingsdialog.cpp | 62 | ||||
| -rw-r--r-- | src/plugins/Visual/analyzer/settingsdialog.h | 46 | ||||
| -rw-r--r-- | src/plugins/Visual/analyzer/settingsdialog.ui | 403 | ||||
| -rw-r--r-- | src/plugins/Visual/analyzer/visualanalyzerfactory.cpp | 57 | ||||
| -rw-r--r-- | src/plugins/Visual/analyzer/visualanalyzerfactory.h | 46 |
16 files changed, 2092 insertions, 0 deletions
diff --git a/src/plugins/Visual/CMakeLists.txt b/src/plugins/Visual/CMakeLists.txt new file mode 100644 index 000000000..df35bdf14 --- /dev/null +++ b/src/plugins/Visual/CMakeLists.txt @@ -0,0 +1,8 @@ +SET(USE_ANALYZER TRUE CACHE BOOL "enable/disable analyzer plugin") + +IF(USE_ANALYZER) +MESSAGE( STATUS "ANALYZER ON") +add_subdirectory(analyzer) +ELSE(USE_ANALYZER) +MESSAGE( STATUS "ANALYZER OFF") +ENDIF(USE_ANALYZER) diff --git a/src/plugins/Visual/Visual.pro b/src/plugins/Visual/Visual.pro new file mode 100644 index 000000000..e30196780 --- /dev/null +++ b/src/plugins/Visual/Visual.pro @@ -0,0 +1,3 @@ +TEMPLATE = subdirs + +SUBDIRS += analyzer 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>&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>&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 |
