aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--qmmp.pri1
-rw-r--r--src/plugins/Input/CMakeLists.txt8
-rw-r--r--src/plugins/Input/Input.pro7
-rw-r--r--src/plugins/Input/modplug/CMakeLists.txt85
-rw-r--r--src/plugins/Input/modplug/archivereader.cpp96
-rw-r--r--src/plugins/Input/modplug/archivereader.h50
-rw-r--r--src/plugins/Input/modplug/decoder_modplug.cpp363
-rw-r--r--src/plugins/Input/modplug/decoder_modplug.h76
-rw-r--r--src/plugins/Input/modplug/decodermodplugfactory.cpp169
-rw-r--r--src/plugins/Input/modplug/decodermodplugfactory.h52
-rw-r--r--src/plugins/Input/modplug/detailsdialog.cpp202
-rw-r--r--src/plugins/Input/modplug/detailsdialog.h45
-rw-r--r--src/plugins/Input/modplug/detailsdialog.ui158
-rw-r--r--src/plugins/Input/modplug/modplug.pro37
-rw-r--r--src/plugins/Input/modplug/settingsdialog.cpp186
-rw-r--r--src/plugins/Input/modplug/settingsdialog.h51
-rw-r--r--src/plugins/Input/modplug/settingsdialog.ui950
17 files changed, 2536 insertions, 0 deletions
diff --git a/qmmp.pri b/qmmp.pri
index ff128b83d..6e7c57780 100644
--- a/qmmp.pri
+++ b/qmmp.pri
@@ -13,5 +13,6 @@ CONFIG += JACK_PLUGIN
CONFIG += FLAC_PLUGIN
CONFIG += MUSEPACK_PLUGIN
CONFIG += FFMPEG_PLUGIN
+CONFIG += MODPLUG_PLUGIN
CONFIG += OSS_PLUGIN
CONFIG += PULSE_AUDIO_PLUGIN
diff --git a/src/plugins/Input/CMakeLists.txt b/src/plugins/Input/CMakeLists.txt
index ef6db0a97..420ec6126 100644
--- a/src/plugins/Input/CMakeLists.txt
+++ b/src/plugins/Input/CMakeLists.txt
@@ -6,6 +6,7 @@ SET(USE_FFMPEG TRUE CACHE BOOL "enable/disable ffmpeg plugin")
SET(USE_MPC TRUE CACHE BOOL "enable/disable mpc plugin")
SET(USE_SNDFILE TRUE CACHE BOOL "enable/disable sndfile plugin")
SET(USE_WAVPACK TRUE CACHE BOOL "enable/disable wavpack plugin")
+SET(USE_MODPLUG TRUE CACHE BOOL "enable/disable modplug plugin")
IF(USE_MAD)
MESSAGE( STATUS "MAD ON")
@@ -55,3 +56,10 @@ add_subdirectory(wavpack)
ELSE(USE_WAVPACK)
MESSAGE( STATUS "WAVPACK OFF")
ENDIF(USE_WAVPACK)
+
+IF(USE_MODPLUG)
+MESSAGE( STATUS "MODPLUG ON")
+add_subdirectory(modplug)
+ELSE(USE_MODPLUG)
+MESSAGE( STATUS "MODPLUG OFF")
+ENDIF(USE_MODPLUG)
diff --git a/src/plugins/Input/Input.pro b/src/plugins/Input/Input.pro
index 18f378419..2b75906fb 100644
--- a/src/plugins/Input/Input.pro
+++ b/src/plugins/Input/Input.pro
@@ -3,6 +3,13 @@ include(../../../qmmp.pri)
SUBDIRS += mad vorbis sndfile wavpack
TEMPLATE = subdirs
+contains(CONFIG, MODPLUG_PLUGIN){
+ SUBDIRS += modplug
+ message(***************************)
+ message(* Modplug plugin enabled *)
+ message(***************************)
+}
+
contains(CONFIG, MUSEPACK_PLUGIN){
SUBDIRS += mpc
message(***************************)
diff --git a/src/plugins/Input/modplug/CMakeLists.txt b/src/plugins/Input/modplug/CMakeLists.txt
new file mode 100644
index 000000000..3754a101a
--- /dev/null
+++ b/src/plugins/Input/modplug/CMakeLists.txt
@@ -0,0 +1,85 @@
+project(libmodplug)
+
+cmake_minimum_required(VERSION 2.4.0)
+
+
+INCLUDE(UsePkgConfig)
+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}/../../../qmmp)
+
+# modplug
+PKGCONFIG(libmodplug MODPLUG_INCLUDE_DIR MODPLUG_LINK_DIR MODPLUG_LINK_FLAGS MODPLUG_CFLAGS)
+
+IF(NOT MODPLUG_LINK_FLAGS)
+ SET(MODPLUG_LINK_FLAGS -lmodplug -lstdc++ -lm)
+ SET(MODPLUG_INCLUDE_DIR /usr/include)
+ SET(MODPLUG_CFLAGS -I/usr/include -I/usr/include/libmodplug)
+ SET(MODPLUG_LINK_DIR /usr/lib)
+ENDIF(NOT MODPLUG_LINK_FLAGS)
+
+ADD_DEFINITIONS(${MODPLUG_CFLAGS})
+include_directories(${CMODPLUG_INCLUDE_DIR})
+link_directories(${MODPLUG_LINK_DIR})
+
+SET(libmodplug_SRCS
+ decoder_modplug.cpp
+ decodermodplugfactory.cpp
+ detailsdialog.cpp
+ settingsdialog.cpp
+ archivereader.cpp
+)
+
+SET(libmodplug_MOC_HDRS
+ decodermodplugfactory.h
+ decoder_modplug.h
+ detailsdialog.h
+ settingsdialog.h
+ archivereader.h
+)
+
+#SET(libmodplug_RCCS translations/translations.qrc)
+
+#QT4_ADD_RESOURCES(libmodplug_RCC_SRCS ${libmodplug_RCCS})
+
+QT4_WRAP_CPP(libmodplug_MOC_SRCS ${libmodplug_MOC_HDRS})
+
+# user interface
+
+
+SET(libmodplug_UIS
+ detailsdialog.ui
+ settingsdialog.ui
+)
+
+QT4_WRAP_UI(libmodplug_UIS_H ${libmodplug_UIS})
+# Don't forget to include output directory, otherwise
+# the UI file won't be wrapped!
+include_directories(${CMAKE_CURRENT_BINARY_DIR})
+
+ADD_LIBRARY(modplug SHARED ${libmodplug_SRCS} ${libmodplug_MOC_SRCS} ${libmodplug_UIS_H}
+ ${libmodplug_RCC_SRCS})
+target_link_libraries(modplug ${QT_LIBRARIES} -lqmmp ${MODPLUG_LINK_FLAGS} ${MODPLUG_CLAGS})
+install(TARGETS modplug DESTINATION ${LIB_DIR}/qmmp/Input)
+
+
diff --git a/src/plugins/Input/modplug/archivereader.cpp b/src/plugins/Input/modplug/archivereader.cpp
new file mode 100644
index 000000000..adba824dc
--- /dev/null
+++ b/src/plugins/Input/modplug/archivereader.cpp
@@ -0,0 +1,96 @@
+/***************************************************************************
+ * Copyright (C) 2008 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 <QProcess>
+
+#include "archivereader.h"
+
+ArchiveReader::ArchiveReader(QObject *parent)
+ : QObject(parent)
+{
+ m_process = new QProcess(this);
+}
+
+
+ArchiveReader::~ArchiveReader()
+{}
+
+bool ArchiveReader::isSupported(const QString &path)
+{
+ QString lPath = path.toLower();
+ return lPath.endsWith(".mdz") ||
+ lPath.endsWith(".s3z") ||
+ lPath.endsWith(".xmz") ||
+ lPath.endsWith(".itz") ||
+ lPath.endsWith(".mdgz") ||
+ lPath.endsWith(".s3gz") ||
+ lPath.endsWith(".xmgz") ||
+ lPath.endsWith(".itgz") ||
+ lPath.endsWith(".mdbz") ||
+ lPath.endsWith(".s3bz") ||
+ lPath.endsWith(".xmbz") ||
+ lPath.endsWith(".itbz");
+}
+
+QByteArray ArchiveReader::unpack(const QString &path)
+{
+ QString lPath = path.toLower();
+ if (path.endsWith(".mdz") ||
+ lPath.endsWith(".s3z") ||
+ lPath.endsWith(".xmz") ||
+ lPath.endsWith(".itz"))
+ return unzip(path);
+ else if (lPath.endsWith(".mdgz") ||
+ lPath.endsWith(".s3gz") ||
+ lPath.endsWith(".xmgz") ||
+ lPath.endsWith(".itgz"))
+ return gunzip(path);
+ else if (lPath.endsWith(".mdbz"))
+ return bunzip2(path);
+
+ return QByteArray();
+}
+
+QByteArray ArchiveReader::unzip(const QString &path)
+{
+ QStringList args;
+ args << "-p" << path;
+ m_process->start("unzip", args);
+ m_process->waitForFinished();
+ return m_process->readAllStandardOutput ();
+}
+
+QByteArray ArchiveReader::gunzip(const QString &path)
+{
+ QStringList args;
+ args << "-c" << path;
+ m_process->start("gunzip", args);
+ m_process->waitForFinished();
+ return m_process->readAllStandardOutput ();
+}
+
+QByteArray ArchiveReader::bunzip2(const QString &path)
+{
+ QStringList args;
+ args << "-c" << path;
+ m_process->start("bunzip2", args);
+ m_process->waitForFinished();
+ return m_process->readAllStandardOutput ();
+}
diff --git a/src/plugins/Input/modplug/archivereader.h b/src/plugins/Input/modplug/archivereader.h
new file mode 100644
index 000000000..347e32203
--- /dev/null
+++ b/src/plugins/Input/modplug/archivereader.h
@@ -0,0 +1,50 @@
+/***************************************************************************
+ * Copyright (C) 2008 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 ARCHIVEREADER_H
+#define ARCHIVEREADER_H
+
+#include <QObject>
+#include <QByteArray>
+
+class QProcess;
+
+/**
+ @author Ilya Kotov <forkotov02@hotmail.ru>
+*/
+class ArchiveReader : public QObject
+{
+Q_OBJECT
+public:
+ ArchiveReader(QObject *parent = 0);
+
+ ~ArchiveReader();
+
+ bool isSupported(const QString &path);
+ QByteArray unpack(const QString &path);
+
+private:
+ QProcess *m_process;
+ QByteArray unzip(const QString &path);
+ QByteArray gunzip(const QString &path);
+ QByteArray bunzip2(const QString &path);
+
+};
+
+#endif
diff --git a/src/plugins/Input/modplug/decoder_modplug.cpp b/src/plugins/Input/modplug/decoder_modplug.cpp
new file mode 100644
index 000000000..26a959e1c
--- /dev/null
+++ b/src/plugins/Input/modplug/decoder_modplug.cpp
@@ -0,0 +1,363 @@
+/***************************************************************************
+ * Copyright (C) 2008 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 <QObject>
+#include <QIODevice>
+#include <QFile>
+#include <QDir>
+#include <QSettings>
+#include <math.h>
+
+#include <libmodplug/stdafx.h>
+#include <libmodplug/it_defs.h>
+#include <libmodplug/sndfile.h>
+
+#include <qmmp/constants.h>
+#include <qmmp/buffer.h>
+#include <qmmp/output.h>
+#include <qmmp/recycler.h>
+
+#include <stdint.h>
+
+#include "archivereader.h"
+#include "decoder_modplug.h"
+
+// Decoder class
+
+DecoderModPlug* DecoderModPlug::m_instance = 0;
+
+DecoderModPlug::DecoderModPlug(QObject *parent, DecoderFactory *d, QIODevice *i, Output *o)
+ : Decoder(parent, d, i, o)
+{
+ m_inited = FALSE;
+ m_user_stop = FALSE;
+ m_output_buf = 0;
+ m_output_bytes = 0;
+ m_output_at = 0;
+ m_bks = 0;
+ m_done = FALSE;
+ m_finish = FALSE;
+ m_freq = 0;
+ m_bitrate = 0;
+ m_seekTime = -1.0;
+ m_totalTime = 0.0;
+ m_chan = 0;
+ m_output_size = 0;
+ //m_modFile = 0;
+ m_soundFile = 0;
+ m_sampleSize = 0;
+ m_instance = this;
+}
+
+DecoderModPlug::~DecoderModPlug()
+{
+ deinit();
+ if (m_output_buf)
+ delete [] m_output_buf;
+ m_output_buf = 0;
+ m_instance = 0;
+}
+
+void DecoderModPlug::stop()
+{
+ m_user_stop = TRUE;
+}
+
+void DecoderModPlug::flush(bool final)
+{
+ ulong min = final ? 0 : m_bks;
+
+ while ((! m_done && ! m_finish) && m_output_bytes > min)
+ {
+ output()->recycler()->mutex()->lock ();
+
+ while ((! m_done && ! m_finish) && output()->recycler()->full())
+ {
+ mutex()->unlock();
+
+ output()->recycler()->cond()->wait(output()->recycler()->mutex());
+
+ mutex()->lock ();
+ m_done = m_user_stop;
+ }
+
+ if (m_user_stop || m_finish)
+ {
+ m_inited = FALSE;
+ m_done = TRUE;
+ }
+ else
+ {
+ m_output_bytes -= produceSound(m_output_buf, m_output_bytes, m_bitrate, m_chan);
+ m_output_size += m_bks;
+ m_output_at = m_output_bytes;
+ }
+
+ if (output()->recycler()->full())
+ {
+ output()->recycler()->cond()->wakeOne();
+ }
+
+ output()->recycler()->mutex()->unlock();
+ }
+}
+
+bool DecoderModPlug::initialize()
+{
+ m_bks = blockSize();
+ m_inited = m_user_stop = m_done = m_finish = FALSE;
+ m_freq = m_bitrate = 0;
+ m_chan = 0;
+ m_output_size = 0;
+ m_seekTime = -1.0;
+ m_totalTime = 0.0;
+
+
+ if (! input())
+ {
+ error("DecoderModPlug: cannot initialize. No input.");
+
+ return FALSE;
+ }
+
+ if (! m_output_buf)
+ m_output_buf = new char[globalBufferSize];
+ m_output_at = 0;
+ m_output_bytes = 0;
+
+ QString filename = qobject_cast<QFile*>(input())->fileName ();
+ ArchiveReader reader(this);
+ if(reader.isSupported(filename))
+ {
+ input()->close();
+ m_input_buf = reader.unpack(filename);
+ }
+ else
+ m_input_buf = input()->readAll();
+
+ if (m_input_buf.isEmpty())
+ {
+ qWarning("DecoderModPlug: error reading moplug file");
+ return FALSE;
+ }
+ m_soundFile = new CSoundFile();
+ readSettings();
+ m_sampleSize = m_bps / 8 * m_chan;
+ m_soundFile->Create((uchar*) m_input_buf.data(), m_input_buf.size());
+ m_bitrate = m_soundFile->GetNumChannels();
+ /*if(!m_modFile)
+ {
+ qWarning("DecoderModPlug: error reading moplug file");
+ return FALSE;
+ }*/
+
+ m_totalTime = (int) m_soundFile->GetSongTime();
+ configure(m_freq, m_chan, m_bps, m_bitrate);
+ m_inited = TRUE;
+ return TRUE;
+}
+
+double DecoderModPlug::lengthInSeconds()
+{
+ if (! m_inited)
+ return 0;
+
+ return m_totalTime;
+}
+
+
+void DecoderModPlug::seek(double pos)
+{
+ m_seekTime = pos;
+}
+
+void DecoderModPlug::deinit()
+{
+ m_inited = m_user_stop = m_done = m_finish = FALSE;
+ m_freq = m_bitrate = 0;
+ m_chan = 0;
+ m_output_size = 0;
+ if (m_soundFile)
+ {
+ m_soundFile->Destroy();
+ delete m_soundFile;
+ m_soundFile = 0;
+ }
+ m_input_buf.clear();
+}
+
+void DecoderModPlug::run()
+{
+ mutex()->lock ();
+
+ ulong len = 0;
+ if (! m_inited)
+ {
+ mutex()->unlock();
+
+ return;
+ }
+ mutex()->unlock();
+ dispatch(DecoderState::Decoding);
+
+ while (! m_done && ! m_finish)
+ {
+ mutex()->lock ();
+
+ //seeking
+
+ if (m_seekTime >= 0.0)
+ {
+ quint32 lMax;
+ quint32 lMaxtime;
+ double lPostime;
+
+ if (m_seekTime > (lMaxtime = m_soundFile->GetSongTime()))
+ m_seekTime = lMaxtime;
+ lMax = m_soundFile->GetMaxPosition();
+ lPostime = float(lMax) / lMaxtime;
+ m_soundFile->SetCurrentPos(int(m_seekTime * lPostime));
+ m_seekTime = -1.0;
+ }
+
+ // decode
+ len = m_bks > (globalBufferSize - m_output_at) ? globalBufferSize - m_output_at : m_bks;
+ len = m_soundFile->Read (m_output_buf + m_output_at, len) * m_sampleSize;
+
+ if (len > 0)
+ {
+ m_output_at += len;
+ m_output_bytes += len;
+
+ if (output())
+ flush();
+
+ }
+ else if (len == 0)
+ {
+ flush(TRUE);
+
+ if (output())
+ {
+ output()->recycler()->mutex()->lock ();
+ // end of stream
+ while (! output()->recycler()->empty() && ! m_user_stop)
+ {
+ output()->recycler()->cond()->wakeOne();
+ mutex()->unlock();
+ output()->recycler()->cond()->wait(output()->recycler()->mutex());
+ mutex()->lock ();
+ }
+ output()->recycler()->mutex()->unlock();
+ }
+
+ m_done = TRUE;
+ if (! m_user_stop)
+ {
+ m_finish = TRUE;
+ }
+ }
+ else
+ {
+ // error in read
+ error("DecoderModPlug: Error while decoding stream, File appears to be "
+ "corrupted");
+ m_finish = TRUE;
+ }
+ mutex()->unlock();
+ }
+
+ mutex()->lock ();
+
+ if (m_finish)
+ dispatch(DecoderState::Finished);
+ else if (m_user_stop)
+ dispatch(DecoderState::Stopped);
+
+ mutex()->unlock();
+
+ deinit();
+}
+
+void DecoderModPlug::readSettings()
+{
+ if (!m_soundFile)
+ return;
+ QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat);
+ settings.beginGroup("ModPlug");
+ CSoundFile::SetWaveConfig
+ (
+ m_freq = settings.value("Frequency", 44100).toInt(),
+ m_bps = settings.value("Bits", 16).toInt(),
+ m_chan = settings.value("Channels", 2).toInt()
+ );
+
+ CSoundFile::SetWaveConfigEx
+ (
+ settings.value("Surround", TRUE).toBool(),
+ TRUE,
+ settings.value("Reverb", TRUE).toBool(),
+ TRUE,
+ settings.value("Megabass", FALSE).toBool(),
+ settings.value("NoiseReduction", FALSE).toBool(),
+ FALSE
+ );
+ if (settings.value("Reverb", TRUE).toBool())
+ {
+ CSoundFile::SetReverbParameters
+ (
+ settings.value("ReverbDepth", 30).toInt(),
+ settings.value("ReverbDelay", 100).toInt()
+ );
+ }
+ if (settings.value("Megabass", FALSE).toBool())
+ {
+ CSoundFile::SetXBassParameters
+ (
+ settings.value("BassAmount", 40).toInt(),
+ settings.value("BassRange", 30).toInt()
+ );
+ }
+ if (settings.value("Surround", TRUE).toBool())
+ {
+ CSoundFile::SetSurroundParameters
+ (
+ settings.value("SurroundDepth", 20).toInt(),
+ settings.value("SurroundDelay", 20).toInt()
+ );
+ }
+ CSoundFile::SetResamplingMode(settings.value("ResamplineMode", SRCMODE_POLYPHASE).toInt());
+ m_soundFile->SetRepeatCount(settings.value("LoopCount", 0).toInt());
+
+
+ //general
+ /*
+ ui.amigaCheckBox->setChecked(settings.value("GrabAmigaMOD", TRUE).toBool());*/
+ //resampling frequency
+ //preamp
+ //ui.preampGroupBox->setChecked(settings.value("PreAmp", FALSE).toBool());
+ //ui.preampSlider->setValue(int(settings.value("PreAmpLevel", 0.0f).toDouble()*10));
+ settings.endGroup();
+}
+
+DecoderModPlug* DecoderModPlug::instance()
+{
+ return m_instance;
+}
diff --git a/src/plugins/Input/modplug/decoder_modplug.h b/src/plugins/Input/modplug/decoder_modplug.h
new file mode 100644
index 000000000..e7f786382
--- /dev/null
+++ b/src/plugins/Input/modplug/decoder_modplug.h
@@ -0,0 +1,76 @@
+/***************************************************************************
+ * Copyright (C) 2008 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 DECODER_MODPLUG_H
+#define DECODER_MODPLUG_H
+
+#include <qmmp/decoder.h>
+
+class CSoundFile;
+
+class DecoderModPlug : public Decoder
+{
+public:
+ DecoderModPlug(QObject *, DecoderFactory *, QIODevice *, Output *);
+ virtual ~DecoderModPlug();
+
+ // Standard Decoder API
+ bool initialize();
+ double lengthInSeconds();
+ void seek(double);
+ void stop();
+
+ void readSettings();
+ static DecoderModPlug* instance();
+
+private:
+ // thread run function
+ void run();
+
+ // helper functions
+ void flush(bool = FALSE);
+ void deinit();
+
+ //ModPlug_Settings m_modSettings;
+ //CSoundFile *m_modFile;
+ CSoundFile *m_soundFile;
+
+ bool m_inited, m_user_stop;
+ int m_bps; //bits per sample
+
+
+ //input buffer
+ QByteArray m_input_buf;
+
+ // output buffer
+ char *m_output_buf;
+ ulong m_output_bytes, m_output_at;
+
+ unsigned int m_bks; //block size
+ bool m_done, m_finish;
+ long m_freq, m_bitrate;
+ int m_chan, m_sampleSize;
+ unsigned long m_output_size;
+ double m_totalTime, m_seekTime;
+ static DecoderModPlug* m_instance;
+};
+
+
+#endif // DECODER_MODPLUG_H
diff --git a/src/plugins/Input/modplug/decodermodplugfactory.cpp b/src/plugins/Input/modplug/decodermodplugfactory.cpp
new file mode 100644
index 000000000..147244839
--- /dev/null
+++ b/src/plugins/Input/modplug/decodermodplugfactory.cpp
@@ -0,0 +1,169 @@
+#include <QtGui>
+
+#include <libmodplug/stdafx.h>
+#include <libmodplug/it_defs.h>
+#include <libmodplug/sndfile.h>
+
+#include "settingsdialog.h"
+#include "detailsdialog.h"
+#include "decoder_modplug.h"
+#include "archivereader.h"
+#include "decodermodplugfactory.h"
+
+
+// DecoderModPlugFactory
+
+bool DecoderModPlugFactory::supports(const QString &source) const
+{
+ QString lExt = source.section(".",-1).toLower();
+ lExt.prepend(".");
+ if (lExt == ".xm")
+ return TRUE;
+ if (lExt == ".amf")
+ return TRUE;
+ if (lExt == ".ams")
+ return TRUE;
+ if (lExt == ".dbm")
+ return TRUE;
+ if (lExt == ".dbf")
+ return TRUE;
+ if (lExt == ".dsm")
+ return TRUE;
+ if (lExt == ".far")
+ return TRUE;
+ if (lExt == ".mdl")
+ return TRUE;
+ if (lExt == ".stm")
+ return TRUE;
+ if (lExt == ".ult")
+ return TRUE;
+ if (lExt == ".j2b")
+ return TRUE;
+ if (lExt == ".mt2")
+ return TRUE;
+ if (lExt == ".mdz")
+ return TRUE;
+ /*if (lExt == ".mdr")
+ return TRUE;*/
+ if (lExt == ".mdgz")
+ return TRUE;
+ if (lExt == ".mdbz")
+ return TRUE;
+ if (lExt == ".s3z")
+ return TRUE;
+ /*if (lExt == ".s3r")
+ return TRUE;*/
+ if (lExt == ".s3gz")
+ return TRUE;
+ if (lExt == ".xmz")
+ return TRUE;
+ /*if (lExt == ".xmr")
+ return TRUE;*/
+ if (lExt == ".xmgz")
+ return TRUE;
+ if (lExt == ".itz")
+ return TRUE;
+ /*if (lExt == ".itr")
+ return TRUE;*/
+ if (lExt == ".itgz")
+ return TRUE;
+ if (lExt == ".dmf")
+ return TRUE;
+ return FALSE;
+}
+
+bool DecoderModPlugFactory::canDecode(QIODevice *) const
+{
+ return FALSE;
+}
+
+const DecoderProperties DecoderModPlugFactory::properties() const
+{
+ DecoderProperties properties;
+ properties.name = tr("ModPlug Plugin");
+ properties.filter = (QString) "*.amf *.ams *.dbm *.dbf *.dsm *.far *.mdl *.stm *.ult" +
+ "*.j2b *.mt2 *.mdz *.mdr *.mdgz *.mdbz *.mod *.s3z *.s3r *.s3gz *.s3m *.xmz"+
+ "*.xmr *.xmgz *.itz *.itr *.itgz *.dmf *.umx *.it *.669 *.xm *.mtm *.psm *.ft2";
+ properties.description = tr("ModPlug Files");
+ //properties.contentType = ;
+ properties.hasAbout = TRUE;
+ properties.hasSettings = TRUE;
+ return properties;
+}
+
+Decoder *DecoderModPlugFactory::create(QObject *parent, QIODevice *input,
+ Output *output)
+{
+ return new DecoderModPlug(parent, this, input, output);
+}
+
+FileTag *DecoderModPlugFactory::createTag(const QString &source)
+{
+ FileTag *ftag = new FileTag();
+ QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat);
+ if(settings.value("UseFileName", FALSE).toBool())
+ {
+ ftag->setValue(FileTag::TITLE, source.section('/',-1));
+ return ftag;
+ }
+ ArchiveReader reader(this);
+ QByteArray buffer;
+ if(reader.isSupported(source))
+ {
+ buffer = reader.unpack(source);
+ }
+ else
+ {
+ QFile file(source);
+ if(!file.open(QIODevice::ReadOnly))
+ {
+ qWarning("DecoderModPlugFactory: error: %s", qPrintable(file.errorString ()));
+ return ftag;
+ }
+ buffer = file.readAll();
+ file.close();
+ }
+ CSoundFile* soundFile = new CSoundFile();
+ soundFile->Create((uchar*) buffer.data(), buffer.size());
+
+ ftag->setValue(FileTag::LENGTH, (int) soundFile->GetSongTime());
+ ftag->setValue(FileTag::TITLE, QString::fromUtf8(soundFile->GetTitle()));
+ soundFile->Destroy();
+ delete soundFile;
+ return ftag;
+}
+
+QObject* DecoderModPlugFactory::showDetails(QWidget *parent, const QString &path)
+{
+ DetailsDialog *d = new DetailsDialog(parent, path);
+ d -> show();
+ return d;
+}
+
+void DecoderModPlugFactory::showSettings(QWidget *parent)
+{
+ SettingsDialog *d = new SettingsDialog(parent);
+ d->show();
+}
+
+void DecoderModPlugFactory::showAbout(QWidget *parent)
+{
+ QMessageBox::about (parent, tr("About ModPlug Audio Plugin"),
+ tr("Qmmp ModPlug Audio Plugin")+"\n"+
+ tr("Writen by: Ilya Kotov <forkotov02@hotmail.ru>")+"\n"+
+ tr("Based on the Modplug Plugin for Xmms")+"\n"+
+ tr("Modplug Plugin developers:")+"\n"+
+ tr("Olivier Lapicque <olivierl@jps.net>")+"\n"+
+ tr("Kenton Varda <temporal@gauge3d.org>")+"\n"+
+ tr("Konstanty Bialkowski <konstanty@ieee.org>"));
+}
+
+QTranslator *DecoderModPlugFactory::createTranslator(QObject *parent)
+{
+ QTranslator *translator = new QTranslator(parent);
+ QString locale = QLocale::system().name();
+ translator->load(QString(":/modplug_plugin_") + locale);
+ return translator;
+}
+
+Q_EXPORT_PLUGIN(DecoderModPlugFactory)
diff --git a/src/plugins/Input/modplug/decodermodplugfactory.h b/src/plugins/Input/modplug/decodermodplugfactory.h
new file mode 100644
index 000000000..20378f739
--- /dev/null
+++ b/src/plugins/Input/modplug/decodermodplugfactory.h
@@ -0,0 +1,52 @@
+/***************************************************************************
+ * Copyright (C) 2008 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 DECODERMODPLUGFACTORY_H
+#define DECODERMODPLUGFACTORY_H
+
+#include <QObject>
+#include <QString>
+#include <QIODevice>
+#include <QWidget>
+
+#include <qmmp/decoder.h>
+#include <qmmp/output.h>
+#include <qmmp/decoderfactory.h>
+#include <qmmp/filetag.h>
+
+
+class DecoderModPlugFactory : public QObject,
+ DecoderFactory
+{
+Q_OBJECT
+Q_INTERFACES(DecoderFactory);
+
+public:
+ bool supports(const QString &source) const;
+ bool canDecode(QIODevice *input) const;
+ const DecoderProperties properties() const;
+ Decoder *create(QObject *, QIODevice *, Output *);
+ FileTag *createTag(const QString &source);
+ QObject* showDetails(QWidget *parent, const QString &path);
+ void showSettings(QWidget *parent);
+ void showAbout(QWidget *parent);
+ QTranslator *createTranslator(QObject *parent);
+};
+
+#endif
diff --git a/src/plugins/Input/modplug/detailsdialog.cpp b/src/plugins/Input/modplug/detailsdialog.cpp
new file mode 100644
index 000000000..881572ecd
--- /dev/null
+++ b/src/plugins/Input/modplug/detailsdialog.cpp
@@ -0,0 +1,202 @@
+/***************************************************************************
+ * Copyright (C) 2008 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 <QFile>
+#include <QFileInfo>
+#include <QTextStream>
+
+#include <stdint.h>
+#include <libmodplug/stdafx.h>
+#include <libmodplug/it_defs.h>
+#include <libmodplug/sndfile.h>
+#include <libmodplug/modplug.h>
+
+#define MAX_MESSAGE_LENGTH 4000
+
+#include "archivereader.h"
+#include "detailsdialog.h"
+
+DetailsDialog::DetailsDialog(QWidget *parent, const QString &path)
+ : QDialog(parent)
+{
+ ui.setupUi(this);
+ setAttribute(Qt::WA_DeleteOnClose);
+ m_path = path;
+ setWindowTitle (path.section('/',-1));
+ ui.pathLineEdit->setText(m_path);
+ ui.nameLabel->setText(tr("File name:")+'\n'+
+ tr("Title:")+'\n'+
+ tr("Type:")+'\n'+
+ tr("Length:")+'\n'+
+ tr("Speed:")+'\n'+
+ tr("Tempo:")+'\n'+
+ tr("Samples:")+'\n'+
+ tr("Instruments:")+'\n'+
+ tr("Patterns:")+'\n'+
+ tr("Channels:"));
+
+ loadInfo();
+}
+
+
+DetailsDialog::~DetailsDialog()
+{}
+
+void DetailsDialog::loadInfo()
+{
+ quint32 lSongTime, lNumSamples, lNumInstruments, i;
+ char lBuffer[33];
+ ArchiveReader reader(this);
+ QByteArray buffer;
+ if(reader.isSupported(m_path))
+ {
+ buffer = reader.unpack(m_path);
+ }
+ else
+ {
+ QFile file(m_path);
+ if(!file.open(QIODevice::ReadOnly))
+ {
+ qWarning("DetailsDialog: error: %s", qPrintable(file.errorString ()));
+ return;
+ }
+ buffer = file.readAll();
+ file.close();
+ }
+
+ CSoundFile* soundFile = new CSoundFile();
+ soundFile->Create((uchar*) buffer.data(), buffer.size());
+
+ QString lInfo = m_path.section('/',-1);
+ lInfo += '\n';
+ lInfo += QString::fromUtf8(soundFile->GetTitle());
+ lInfo += '\n';
+
+ switch(soundFile->GetType())
+ {
+ case MOD_TYPE_MOD:
+ lInfo+= "ProTracker";
+ break;
+ case MOD_TYPE_S3M:
+ lInfo+= "Scream Tracker 3";
+ break;
+ case MOD_TYPE_XM:
+ lInfo+= "Fast Tracker 2";
+ break;
+ case MOD_TYPE_IT:
+ lInfo+= "Impulse Tracker";
+ break;
+ case MOD_TYPE_MED:
+ lInfo+= "OctaMed";
+ break;
+ case MOD_TYPE_MTM:
+ lInfo+= "MTM";
+ break;
+ case MOD_TYPE_669:
+ lInfo+= "669 Composer / UNIS 669";
+ break;
+ case MOD_TYPE_ULT:
+ lInfo+= "ULT";
+ break;
+ case MOD_TYPE_STM:
+ lInfo+= "Scream Tracker";
+ break;
+ case MOD_TYPE_FAR:
+ lInfo+= "Farandole";
+ break;
+ case MOD_TYPE_AMF:
+ lInfo+= "ASYLUM Music Format";
+ break;
+ case MOD_TYPE_AMS:
+ lInfo+= "AMS module";
+ break;
+ case MOD_TYPE_DSM:
+ lInfo+= "DSIK Internal Format";
+ break;
+ case MOD_TYPE_MDL:
+ lInfo+= "DigiTracker";
+ break;
+ case MOD_TYPE_OKT:
+ lInfo+= "Oktalyzer";
+ break;
+ case MOD_TYPE_DMF:
+ lInfo+= "Delusion Digital Music Fileformat (X-Tracker)";
+ break;
+ case MOD_TYPE_PTM:
+ lInfo+= "PolyTracker";
+ break;
+ case MOD_TYPE_DBM:
+ lInfo+= "DigiBooster Pro";
+ break;
+ case MOD_TYPE_MT2:
+ lInfo+= "MT2";
+ break;
+ case MOD_TYPE_AMF0:
+ lInfo+= "AMF0";
+ break;
+ case MOD_TYPE_PSM:
+ lInfo+= "PSM";
+ break;
+ default:
+ lInfo+= "Unknown";
+ break;
+ }
+ lInfo += '\n';
+
+ lSongTime = soundFile->GetSongTime();
+ QString text = QString("%1").arg(lSongTime/60);
+ text +=":"+QString("%1").arg(lSongTime%60,2,10,QChar('0'));
+ lInfo += text;
+ lInfo += '\n';
+
+ QTextStream lStrStream(&lInfo);
+ lStrStream << (int)soundFile->GetMusicSpeed() << '\n';
+ lStrStream << (int)soundFile->GetMusicTempo() << '\n';
+ lStrStream << (int)(lNumSamples = soundFile->GetNumSamples()) << '\n';
+ lStrStream << (int)(lNumInstruments = soundFile->GetNumInstruments());
+ lStrStream << '\n';
+ lStrStream << (int)(soundFile->GetNumPatterns()) << '\n';
+ lStrStream << (int)soundFile->GetNumChannels();
+ ui.valueLabel->setText(lInfo);
+ lInfo.clear();
+ for(i = 0; i < lNumSamples; i++)
+ {
+ soundFile->GetSampleName(i, lBuffer);
+ lInfo += QString::fromUtf8(lBuffer);
+ lInfo += '\n';
+ }
+ ui.samplesTextEdit->setText(lInfo.trimmed ());
+ lInfo.clear();
+ for(i = 0; i < lNumInstruments; i++)
+ {
+ soundFile->GetInstrumentName(i, lBuffer);
+ lInfo += QString::fromUtf8(lBuffer);
+ lInfo += '\n';
+ }
+ ui.instrumentsTextEdit->setText(lInfo.trimmed ());
+ lInfo.clear();
+ char message[MAX_MESSAGE_LENGTH];
+ int length = soundFile->GetSongComments(message, MAX_MESSAGE_LENGTH, 80);
+ if (length != 0)
+ ui.instrumentsTextEdit->setText(QString::fromUtf8(message).trimmed ());
+
+ soundFile->Destroy();
+ delete soundFile;
+}
+
diff --git a/src/plugins/Input/modplug/detailsdialog.h b/src/plugins/Input/modplug/detailsdialog.h
new file mode 100644
index 000000000..a6806ff58
--- /dev/null
+++ b/src/plugins/Input/modplug/detailsdialog.h
@@ -0,0 +1,45 @@
+/***************************************************************************
+ * Copyright (C) 2008 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 DETAILSDIALOG_H
+#define DETAILSDIALOG_H
+
+#include <QDialog>
+
+#include "ui_detailsdialog.h"
+
+/**
+ @author Ilya Kotov <forkotov02@hotmail.ru>
+*/
+class DetailsDialog : public QDialog
+{
+Q_OBJECT
+public:
+ DetailsDialog(QWidget *parent = 0, const QString &path = 0);
+
+ ~DetailsDialog();
+
+private:
+ Ui::DetailsDialog ui;
+ QString m_path;
+ void loadInfo();
+
+};
+
+#endif
diff --git a/src/plugins/Input/modplug/detailsdialog.ui b/src/plugins/Input/modplug/detailsdialog.ui
new file mode 100644
index 000000000..e99ed5836
--- /dev/null
+++ b/src/plugins/Input/modplug/detailsdialog.ui
@@ -0,0 +1,158 @@
+<ui version="4.0" >
+ <class>DetailsDialog</class>
+ <widget class="QDialog" name="DetailsDialog" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>328</width>
+ <height>376</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>MOD Info</string>
+ </property>
+ <layout class="QGridLayout" >
+ <item row="0" column="0" colspan="2" >
+ <widget class="QLineEdit" name="pathLineEdit" >
+ <property name="readOnly" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0" colspan="2" >
+ <widget class="QTabWidget" name="tabWidget" >
+ <property name="currentIndex" >
+ <number>0</number>
+ </property>
+ <widget class="QWidget" name="tab" >
+ <attribute name="title" >
+ <string>General</string>
+ </attribute>
+ <layout class="QHBoxLayout" >
+ <item>
+ <widget class="QLabel" name="nameLabel" >
+ <property name="text" >
+ <string>-</string>
+ </property>
+ <property name="alignment" >
+ <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="valueLabel" >
+ <property name="text" >
+ <string>-</string>
+ </property>
+ <property name="alignment" >
+ <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="tab_2" >
+ <attribute name="title" >
+ <string>Samples</string>
+ </attribute>
+ <layout class="QVBoxLayout" >
+ <item>
+ <widget class="QTextEdit" name="samplesTextEdit" >
+ <property name="readOnly" >
+ <bool>true</bool>
+ </property>
+ <property name="html" >
+ <string>&lt;html>&lt;head>&lt;meta name="qrichtext" content="1" />&lt;style type="text/css">
+p, li { white-space: pre-wrap; }
+&lt;/style>&lt;/head>&lt;body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;">
+&lt;p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">&lt;/p>&lt;/body>&lt;/html></string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="tab_3" >
+ <attribute name="title" >
+ <string>Instruments</string>
+ </attribute>
+ <layout class="QVBoxLayout" >
+ <item>
+ <widget class="QTextEdit" name="instrumentsTextEdit" >
+ <property name="readOnly" >
+ <bool>true</bool>
+ </property>
+ <property name="html" >
+ <string>&lt;html>&lt;head>&lt;meta name="qrichtext" content="1" />&lt;style type="text/css">
+p, li { white-space: pre-wrap; }
+&lt;/style>&lt;/head>&lt;body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;">
+&lt;p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">&lt;/p>&lt;/body>&lt;/html></string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="tab_4" >
+ <attribute name="title" >
+ <string>Message</string>
+ </attribute>
+ <layout class="QHBoxLayout" >
+ <item>
+ <widget class="QTextEdit" name="messageTextEdit" >
+ <property name="readOnly" >
+ <bool>true</bool>
+ </property>
+ <property name="html" >
+ <string>&lt;html>&lt;head>&lt;meta name="qrichtext" content="1" />&lt;style type="text/css">
+p, li { white-space: pre-wrap; }
+&lt;/style>&lt;/head>&lt;body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;">
+&lt;p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">&lt;/p>&lt;/body>&lt;/html></string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </item>
+ <item row="2" column="0" >
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>171</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="2" column="1" >
+ <widget class="QPushButton" name="closeButton" >
+ <property name="text" >
+ <string>Close</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>closeButton</sender>
+ <signal>clicked()</signal>
+ <receiver>DetailsDialog</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>271</x>
+ <y>311</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>120</x>
+ <y>325</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/src/plugins/Input/modplug/modplug.pro b/src/plugins/Input/modplug/modplug.pro
new file mode 100644
index 000000000..0e088fb7c
--- /dev/null
+++ b/src/plugins/Input/modplug/modplug.pro
@@ -0,0 +1,37 @@
+include(../../plugins.pri)
+
+FORMS += detailsdialog.ui \
+ settingsdialog.ui
+HEADERS += decodermodplugfactory.h \
+ decoder_modplug.h \
+ detailsdialog.h \
+ settingsdialog.h \
+ archivereader.h
+SOURCES += decoder_modplug.cpp \
+ decodermodplugfactory.cpp \
+ detailsdialog.cpp \
+ settingsdialog.cpp \
+ archivereader.cpp
+
+TARGET =$$PLUGINS_PREFIX/Input/modplug
+QMAKE_CLEAN =$$PLUGINS_PREFIX/Input/libmodplug.so
+
+
+INCLUDEPATH += ../../../
+CONFIG += release \
+warn_on \
+plugin \
+link_pkgconfig
+TEMPLATE = lib
+QMAKE_LIBDIR += ../../../../lib
+LIBS += -lqmmp -L/usr/lib -I/usr/include
+PKGCONFIG += libmodplug
+#TRANSLATIONS = translations/modplug_plugin_ru.ts
+#RESOURCES = translations/translations.qrc
+
+isEmpty(LIB_DIR){
+ LIB_DIR = /lib
+}
+
+target.path = $$LIB_DIR/qmmp/Input
+INSTALLS += target
diff --git a/src/plugins/Input/modplug/settingsdialog.cpp b/src/plugins/Input/modplug/settingsdialog.cpp
new file mode 100644
index 000000000..e655e9df5
--- /dev/null
+++ b/src/plugins/Input/modplug/settingsdialog.cpp
@@ -0,0 +1,186 @@
+/***************************************************************************
+ * Copyright (C) 2008 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 <libmodplug/stdafx.h>
+#include <libmodplug/it_defs.h>
+#include <libmodplug/sndfile.h>
+
+#include "decoder_modplug.h"
+#include "settingsdialog.h"
+
+SettingsDialog::SettingsDialog(QWidget *parent)
+ : QDialog(parent)
+{
+ ui.setupUi(this);
+ setAttribute(Qt::WA_DeleteOnClose);
+
+ QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat);
+ settings.beginGroup("ModPlug");
+ //general
+ ui.noiseCheckBox->setChecked(settings.value("NoiseReduction", FALSE).toBool());
+ ui.fileNameCheckBox->setChecked(settings.value("UseFileName", FALSE).toBool());
+ ui.amigaCheckBox->setChecked(settings.value("GrabAmigaMOD", TRUE).toBool());
+ //settings.value("Oversampling", TRUE).toBool();
+ //settings.value("VolumeRamp", TRUE).toBool();
+ //settings.value("FastInfo", TRUE).toBool();
+ //channels number
+ if (settings.value("Channels", 2).toInt() == 2)
+ ui.stereoRadioButton->setChecked(TRUE);
+ else
+ ui.monoRadioButton->setChecked(TRUE);
+ //bits number
+ if (settings.value("Bits", 16).toInt() == 8)
+ ui.bit8RadioButton->setChecked(TRUE);
+ else
+ ui.bit16RadioButton->setChecked(TRUE);
+ //resampling frequency
+ int freq = settings.value("Frequency", 44100).toInt();
+ if (freq == 48000)
+ ui.khz48RadioButton->setChecked(TRUE);
+ else if (freq == 44100)
+ ui.khz44RadioButton->setChecked(TRUE);
+ else if (freq == 22050)
+ ui.khz22RadioButton->setChecked(TRUE);
+ else
+ ui.khz11RadioButton->setChecked(TRUE);
+ //resampling mode
+ int res = settings.value("ResamplineMode", SRCMODE_POLYPHASE).toInt();
+ if (res == SRCMODE_NEAREST)
+ ui.resampNearestRadioButton->setChecked(TRUE);
+ else if (res == SRCMODE_LINEAR)
+ ui.resampLinearRadioButton->setChecked(TRUE);
+ else if (res == SRCMODE_SPLINE)
+ ui.resampSplineRadioButton->setChecked(TRUE);
+ else
+ ui.resampPolyphaseRadioButton->setChecked(TRUE);
+ //reverberation
+ ui.reverbGroupBox->setChecked(settings.value("Reverb", TRUE).toBool());
+ ui.reverbDepthSlider->setValue(settings.value("ReverbDepth", 30).toInt());
+ ui.reverbDelaySlider->setValue(settings.value("ReverbDelay", 100).toInt());
+ //surround
+ ui.surGroupBox->setChecked(settings.value("Surround", TRUE).toBool());
+ ui.surDepthSlider->setValue(settings.value("SurroundDepth", 20).toInt());
+ ui.surDelaySlider->setValue(settings.value("SurroundDelay", 20).toInt());
+ //bass
+ ui.bassGroupBox->setChecked(settings.value("Megabass", FALSE).toBool());
+ ui.bassAmountSlider->setValue(settings.value("BassAmount", 40).toInt());
+ ui.bassRangeSlider->setValue(settings.value("BassRange", 30).toInt());
+ //preamp
+ ui.preampGroupBox->setChecked(settings.value("PreAmp", FALSE).toBool());
+ connect(ui.preampSlider, SIGNAL(valueChanged(int)), SLOT(setPreamp(int)));
+ ui.preampSlider->setValue(int(settings.value("PreAmpLevel", 0.0f).toDouble()*10));
+ //looping
+ int l = settings.value("LoopCount", 0).toInt();
+ if (l == 0)
+ ui.dontLoopRadioButton->setChecked(TRUE);
+ else if (l < 0)
+ ui.loopForeverRadioButton->setChecked(TRUE);
+ else
+ {
+ ui.loopRadioButton->setChecked(TRUE);
+ ui.loopSpinBox->setValue(l);
+ }
+ settings.endGroup();
+ connect(ui.applyButton, SIGNAL(clicked()), SLOT(writeSettings()));
+}
+
+
+SettingsDialog::~SettingsDialog()
+{}
+
+void SettingsDialog::writeSettings()
+{
+ QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat);
+ settings.beginGroup("ModPlug");
+ //general
+ settings.setValue("NoiseReduction", ui.noiseCheckBox->isChecked());
+ settings.setValue("UseFileName", ui.fileNameCheckBox->isChecked());
+ settings.setValue("GrabAmigaMOD", ui.amigaCheckBox->isChecked());
+ //settings.value("Oversampling", TRUE).toBool();
+ //settings.value("VolumeRamp", TRUE).toBool();
+ //settings.value("FastInfo", TRUE).toBool();
+ //channels number
+ settings.setValue("Channels", ui.stereoRadioButton->isChecked() ? 2 : 1 );
+ //bits number
+ settings.setValue("Bits", ui.bit8RadioButton->isChecked() ? 8 : 16 );
+ //resampling frequency
+ if(ui.khz48RadioButton->isChecked())
+ settings.setValue("Frequency", 48000);
+ else if(ui.khz44RadioButton->isChecked())
+ settings.setValue("Frequency", 44100);
+ else if(ui.khz22RadioButton->isChecked())
+ settings.setValue("Frequency", 22050);
+ else
+ settings.setValue("Frequency", 11025);
+ //resampling mode
+ if (ui.resampNearestRadioButton->isChecked())
+ settings.setValue("ResamplineMode", SRCMODE_NEAREST);
+ else if (ui.resampLinearRadioButton->isChecked())
+ settings.setValue("ResamplineMode", SRCMODE_LINEAR);
+ else if (ui.resampSplineRadioButton->isChecked())
+ settings.setValue("ResamplineMode", SRCMODE_SPLINE);
+ else
+ settings.setValue("ResamplineMode", SRCMODE_POLYPHASE);
+ //reverberation
+ settings.setValue("Reverb", ui.reverbGroupBox->isChecked());
+ settings.setValue("ReverbDepth", ui.reverbDepthSlider->value());
+ settings.setValue("ReverbDelay", ui.reverbDelaySlider->value());
+ //surround
+ settings.setValue("Surround", ui.surGroupBox->isChecked());
+ settings.setValue("SurroundDepth", ui.surDepthSlider->value());
+ settings.setValue("SurroundDelay", ui.surDelaySlider->value());
+ //bass
+ settings.setValue("Megabass", ui.bassGroupBox->isChecked());
+ settings.setValue("BassAmount", ui.bassAmountSlider->value());
+ settings.setValue("BassRange", ui.bassRangeSlider->value());
+ //preamp
+ settings.setValue("PreAmp", ui.preampGroupBox->isChecked());
+ connect(ui.preampSlider, SIGNAL(valueChanged(int)), SLOT(setPreamp(int)));
+ settings.setValue("PreAmpLevel", (double) ui.preampSlider->value()/10);
+ //looping
+ if (ui.dontLoopRadioButton->isChecked())
+ settings.setValue("LoopCount", 0);
+ else if(ui.loopForeverRadioButton->isChecked())
+ settings.setValue("LoopCount", -1);
+ else
+ settings.setValue("LoopCount", ui.loopSpinBox->value());
+ settings.endGroup();
+ //apply settings for the created decoder
+ if(DecoderModPlug::instance())
+ {
+ DecoderModPlug::instance()->mutex()->lock();
+ DecoderModPlug::instance()->readSettings();
+ DecoderModPlug::instance()->mutex()->unlock();
+ }
+}
+
+void SettingsDialog::setPreamp(int preamp)
+{
+ ui.preampLabel->setText(QString("%1").arg((double) preamp/10));
+}
+
+void SettingsDialog::accept()
+{
+ writeSettings();
+ QDialog::accept();
+}
diff --git a/src/plugins/Input/modplug/settingsdialog.h b/src/plugins/Input/modplug/settingsdialog.h
new file mode 100644
index 000000000..c25b881e7
--- /dev/null
+++ b/src/plugins/Input/modplug/settingsdialog.h
@@ -0,0 +1,51 @@
+/***************************************************************************
+ * Copyright (C) 2008 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();
+
+public slots:
+ virtual void accept();
+
+private slots:
+ void writeSettings();
+ void setPreamp(int);
+
+private:
+ Ui::SettingsDialog ui;
+
+};
+
+#endif
diff --git a/src/plugins/Input/modplug/settingsdialog.ui b/src/plugins/Input/modplug/settingsdialog.ui
new file mode 100644
index 000000000..8f4fe4eb6
--- /dev/null
+++ b/src/plugins/Input/modplug/settingsdialog.ui
@@ -0,0 +1,950 @@
+<ui version="4.0" >
+ <class>SettingsDialog</class>
+ <widget class="QDialog" name="SettingsDialog" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>465</width>
+ <height>378</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Dialog</string>
+ </property>
+ <layout class="QGridLayout" >
+ <item row="0" column="0" colspan="4" >
+ <widget class="QTabWidget" name="tabWidget" >
+ <property name="currentIndex" >
+ <number>0</number>
+ </property>
+ <widget class="QWidget" name="tab" >
+ <attribute name="title" >
+ <string>Quality</string>
+ </attribute>
+ <layout class="QGridLayout" >
+ <item row="0" column="0" >
+ <widget class="QGroupBox" name="groupBox" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Preferred" hsizetype="Preferred" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title" >
+ <string>Resolution</string>
+ </property>
+ <layout class="QVBoxLayout" >
+ <item>
+ <widget class="QRadioButton" name="bit16RadioButton" >
+ <property name="text" >
+ <string>16 bit</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="bit8RadioButton" >
+ <property name="text" >
+ <string>8 bit</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="0" column="1" colspan="2" >
+ <widget class="QGroupBox" name="groupBox_2" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Preferred" hsizetype="Preferred" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title" >
+ <string>Channels</string>
+ </property>
+ <layout class="QVBoxLayout" >
+ <item>
+ <widget class="QRadioButton" name="stereoRadioButton" >
+ <property name="text" >
+ <string>Stereo</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="monoRadioButton" >
+ <property name="text" >
+ <string>Mono (downmix)</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="1" column="0" colspan="2" >
+ <widget class="QGroupBox" name="groupBox_3" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Expanding" hsizetype="Preferred" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title" >
+ <string>Resampling</string>
+ </property>
+ <layout class="QVBoxLayout" >
+ <item>
+ <widget class="QRadioButton" name="resampNearestRadioButton" >
+ <property name="text" >
+ <string>Nearest (fastest)</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="resampLinearRadioButton" >
+ <property name="text" >
+ <string>Linear (fast)</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="resampSplineRadioButton" >
+ <property name="text" >
+ <string>Spline (good quality)</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="resampPolyphaseRadioButton" >
+ <property name="text" >
+ <string>8-tap Fir (extremely high quality)</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="1" column="2" >
+ <widget class="QGroupBox" name="groupBox_4" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Expanding" hsizetype="Preferred" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title" >
+ <string>Sampling Rate</string>
+ </property>
+ <layout class="QVBoxLayout" >
+ <item>
+ <widget class="QRadioButton" name="khz48RadioButton" >
+ <property name="text" >
+ <string>48000 Hz</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="khz44RadioButton" >
+ <property name="text" >
+ <string>44100 Hz</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="khz22RadioButton" >
+ <property name="text" >
+ <string>22050 Hz</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="khz11RadioButton" >
+ <property name="text" >
+ <string>11025 Hz</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="tab_2" >
+ <attribute name="title" >
+ <string>Effects</string>
+ </attribute>
+ <layout class="QGridLayout" >
+ <item row="0" column="0" >
+ <widget class="QGroupBox" name="reverbGroupBox" >
+ <property name="title" >
+ <string>Reverb</string>
+ </property>
+ <property name="checkable" >
+ <bool>true</bool>
+ </property>
+ <property name="checked" >
+ <bool>true</bool>
+ </property>
+ <layout class="QGridLayout" >
+ <item row="0" column="0" >
+ <widget class="QLabel" name="label_3" >
+ <property name="text" >
+ <string>Depth</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1" >
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>10</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="0" column="2" >
+ <widget class="QLabel" name="label_9" >
+ <property name="minimumSize" >
+ <size>
+ <width>40</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="frameShape" >
+ <enum>QFrame::Panel</enum>
+ </property>
+ <property name="frameShadow" >
+ <enum>QFrame::Sunken</enum>
+ </property>
+ <property name="text" >
+ <string>0</string>
+ </property>
+ <property name="alignment" >
+ <set>Qt::AlignCenter</set>
+ </property>
+ <property name="wordWrap" >
+ <bool>false</bool>
+ </property>
+ <property name="margin" >
+ <number>2</number>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0" colspan="3" >
+ <widget class="QSlider" name="reverbDepthSlider" >
+ <property name="maximum" >
+ <number>100</number>
+ </property>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0" >
+ <widget class="QLabel" name="label_4" >
+ <property name="text" >
+ <string>Delay</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1" >
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>10</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="2" column="2" >
+ <widget class="QLabel" name="label_10" >
+ <property name="minimumSize" >
+ <size>
+ <width>35</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="frameShape" >
+ <enum>QFrame::Panel</enum>
+ </property>
+ <property name="frameShadow" >
+ <enum>QFrame::Sunken</enum>
+ </property>
+ <property name="text" >
+ <string>40</string>
+ </property>
+ <property name="alignment" >
+ <set>Qt::AlignCenter</set>
+ </property>
+ <property name="wordWrap" >
+ <bool>false</bool>
+ </property>
+ <property name="margin" >
+ <number>2</number>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0" colspan="3" >
+ <widget class="QSlider" name="reverbDelaySlider" >
+ <property name="minimum" >
+ <number>40</number>
+ </property>
+ <property name="maximum" >
+ <number>200</number>
+ </property>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="0" column="1" >
+ <widget class="QGroupBox" name="bassGroupBox" >
+ <property name="title" >
+ <string>Bass Boost</string>
+ </property>
+ <property name="checkable" >
+ <bool>true</bool>
+ </property>
+ <property name="checked" >
+ <bool>true</bool>
+ </property>
+ <layout class="QGridLayout" >
+ <item row="0" column="0" >
+ <widget class="QLabel" name="label_5" >
+ <property name="text" >
+ <string>Amount</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1" >
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>10</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="0" column="2" >
+ <widget class="QLabel" name="label_13" >
+ <property name="minimumSize" >
+ <size>
+ <width>40</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="frameShape" >
+ <enum>QFrame::Panel</enum>
+ </property>
+ <property name="frameShadow" >
+ <enum>QFrame::Sunken</enum>
+ </property>
+ <property name="text" >
+ <string>0</string>
+ </property>
+ <property name="alignment" >
+ <set>Qt::AlignCenter</set>
+ </property>
+ <property name="wordWrap" >
+ <bool>false</bool>
+ </property>
+ <property name="margin" >
+ <number>2</number>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0" colspan="3" >
+ <widget class="QSlider" name="bassAmountSlider" >
+ <property name="maximum" >
+ <number>100</number>
+ </property>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0" >
+ <widget class="QLabel" name="label_6" >
+ <property name="text" >
+ <string>Range</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1" >
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>10</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="2" column="2" >
+ <widget class="QLabel" name="label_14" >
+ <property name="minimumSize" >
+ <size>
+ <width>35</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="frameShape" >
+ <enum>QFrame::Panel</enum>
+ </property>
+ <property name="frameShadow" >
+ <enum>QFrame::Sunken</enum>
+ </property>
+ <property name="text" >
+ <string>10</string>
+ </property>
+ <property name="alignment" >
+ <set>Qt::AlignCenter</set>
+ </property>
+ <property name="wordWrap" >
+ <bool>false</bool>
+ </property>
+ <property name="margin" >
+ <number>2</number>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0" colspan="3" >
+ <widget class="QSlider" name="bassRangeSlider" >
+ <property name="minimum" >
+ <number>10</number>
+ </property>
+ <property name="maximum" >
+ <number>100</number>
+ </property>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="1" column="0" >
+ <widget class="QGroupBox" name="surGroupBox" >
+ <property name="title" >
+ <string>Surround</string>
+ </property>
+ <property name="checkable" >
+ <bool>true</bool>
+ </property>
+ <layout class="QGridLayout" >
+ <item row="0" column="0" >
+ <widget class="QLabel" name="label" >
+ <property name="text" >
+ <string>Depth</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1" >
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>10</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="0" column="2" >
+ <widget class="QLabel" name="label_11" >
+ <property name="minimumSize" >
+ <size>
+ <width>35</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="frameShape" >
+ <enum>QFrame::Panel</enum>
+ </property>
+ <property name="frameShadow" >
+ <enum>QFrame::Sunken</enum>
+ </property>
+ <property name="text" >
+ <string>0</string>
+ </property>
+ <property name="alignment" >
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0" colspan="3" >
+ <widget class="QSlider" name="surDepthSlider" >
+ <property name="maximum" >
+ <number>100</number>
+ </property>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0" >
+ <widget class="QLabel" name="label_2" >
+ <property name="text" >
+ <string>Delay</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1" >
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>10</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="2" column="2" >
+ <widget class="QLabel" name="label_12" >
+ <property name="minimumSize" >
+ <size>
+ <width>35</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="frameShape" >
+ <enum>QFrame::Panel</enum>
+ </property>
+ <property name="frameShadow" >
+ <enum>QFrame::Sunken</enum>
+ </property>
+ <property name="text" >
+ <string>5</string>
+ </property>
+ <property name="alignment" >
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0" colspan="3" >
+ <widget class="QSlider" name="surDelaySlider" >
+ <property name="minimum" >
+ <number>5</number>
+ </property>
+ <property name="maximum" >
+ <number>40</number>
+ </property>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="1" column="1" >
+ <widget class="QGroupBox" name="preampGroupBox" >
+ <property name="title" >
+ <string>Preamp</string>
+ </property>
+ <property name="checkable" >
+ <bool>true</bool>
+ </property>
+ <layout class="QGridLayout" >
+ <item row="0" column="0" >
+ <widget class="QLabel" name="label_7" >
+ <property name="text" >
+ <string>Volume</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1" >
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>10</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="0" column="2" >
+ <widget class="QLabel" name="preampLabel" >
+ <property name="minimumSize" >
+ <size>
+ <width>35</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="frameShape" >
+ <enum>QFrame::Panel</enum>
+ </property>
+ <property name="frameShadow" >
+ <enum>QFrame::Sunken</enum>
+ </property>
+ <property name="text" >
+ <string>0</string>
+ </property>
+ <property name="alignment" >
+ <set>Qt::AlignCenter</set>
+ </property>
+ <property name="wordWrap" >
+ <bool>false</bool>
+ </property>
+ <property name="margin" >
+ <number>2</number>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0" colspan="3" >
+ <widget class="QSlider" name="preampSlider" >
+ <property name="minimum" >
+ <number>-30</number>
+ </property>
+ <property name="maximum" >
+ <number>30</number>
+ </property>
+ <property name="singleStep" >
+ <number>0</number>
+ </property>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="tickPosition" >
+ <enum>QSlider::TicksBelow</enum>
+ </property>
+ <property name="tickInterval" >
+ <number>30</number>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1" >
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>20</width>
+ <height>16</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="tab_3" >
+ <attribute name="title" >
+ <string>Misc</string>
+ </attribute>
+ <layout class="QVBoxLayout" >
+ <item>
+ <widget class="QGroupBox" name="groupBox_9" >
+ <property name="title" >
+ <string>General</string>
+ </property>
+ <layout class="QGridLayout" >
+ <item row="0" column="0" >
+ <widget class="QCheckBox" name="fileNameCheckBox" >
+ <property name="text" >
+ <string>Use filename as song title</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1" >
+ <widget class="QCheckBox" name="noiseCheckBox" >
+ <property name="text" >
+ <string>Noise reduction</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0" >
+ <widget class="QCheckBox" name="checkBox_6" >
+ <property name="enabled" >
+ <bool>false</bool>
+ </property>
+ <property name="text" >
+ <string>Fast playlist info</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1" >
+ <widget class="QCheckBox" name="amigaCheckBox" >
+ <property name="text" >
+ <string>Play Amiga MOD</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="groupBox_10" >
+ <property name="title" >
+ <string>Looping</string>
+ </property>
+ <layout class="QGridLayout" >
+ <item row="0" column="0" >
+ <widget class="QRadioButton" name="dontLoopRadioButton" >
+ <property name="text" >
+ <string>Don't loop</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0" >
+ <widget class="QRadioButton" name="loopRadioButton" >
+ <property name="text" >
+ <string>Loop</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1" >
+ <widget class="QSpinBox" name="loopSpinBox" >
+ <property name="maximum" >
+ <number>100</number>
+ </property>
+ <property name="value" >
+ <number>1</number>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="2" >
+ <widget class="QLabel" name="label_8" >
+ <property name="text" >
+ <string>time(s)</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="3" >
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>10</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="2" column="0" colspan="2" >
+ <widget class="QRadioButton" name="loopForeverRadioButton" >
+ <property name="text" >
+ <string>Loop forever</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </item>
+ <item row="1" column="0" >
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>211</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="1" column="1" >
+ <widget class="QPushButton" name="okButton" >
+ <property name="text" >
+ <string>OK</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="2" >
+ <widget class="QPushButton" name="applyButton" >
+ <property name="text" >
+ <string>Apply</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="3" >
+ <widget class="QPushButton" name="cancelButton" >
+ <property name="text" >
+ <string>Cancel</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>reverbDepthSlider</sender>
+ <signal>valueChanged(int)</signal>
+ <receiver>label_9</receiver>
+ <slot>setNum(int)</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>198</x>
+ <y>101</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>199</x>
+ <y>85</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>reverbDelaySlider</sender>
+ <signal>valueChanged(int)</signal>
+ <receiver>label_10</receiver>
+ <slot>setNum(int)</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>170</x>
+ <y>153</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>179</x>
+ <y>126</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>surDepthSlider</sender>
+ <signal>valueChanged(int)</signal>
+ <receiver>label_11</receiver>
+ <slot>setNum(int)</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>200</x>
+ <y>253</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>199</x>
+ <y>231</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>surDelaySlider</sender>
+ <signal>valueChanged(int)</signal>
+ <receiver>label_12</receiver>
+ <slot>setNum(int)</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>172</x>
+ <y>298</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>187</x>
+ <y>276</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>bassAmountSlider</sender>
+ <signal>valueChanged(int)</signal>
+ <receiver>label_13</receiver>
+ <slot>setNum(int)</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>421</x>
+ <y>102</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>420</x>
+ <y>87</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>bassRangeSlider</sender>
+ <signal>valueChanged(int)</signal>
+ <receiver>label_14</receiver>
+ <slot>setNum(int)</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>392</x>
+ <y>159</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>397</x>
+ <y>137</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>cancelButton</sender>
+ <signal>clicked()</signal>
+ <receiver>SettingsDialog</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>430</x>
+ <y>356</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>130</x>
+ <y>365</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>okButton</sender>
+ <signal>clicked()</signal>
+ <receiver>SettingsDialog</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>237</x>
+ <y>364</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>33</x>
+ <y>352</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>