aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt1
-rw-r--r--src/plugins/Input/CMakeLists.txt5
-rw-r--r--src/plugins/Input/Input.pro2
-rw-r--r--src/plugins/Input/cue/CMakeLists.txt66
-rw-r--r--src/plugins/Input/cue/cue.pro36
-rw-r--r--src/plugins/Input/cue/cueparser.cpp173
-rw-r--r--src/plugins/Input/cue/cueparser.h57
-rw-r--r--src/plugins/Input/cue/decoder_cue.cpp208
-rw-r--r--src/plugins/Input/cue/decoder_cue.h82
-rw-r--r--src/plugins/Input/cue/decodercuefactory.cpp91
-rw-r--r--src/plugins/Input/cue/decodercuefactory.h51
-rw-r--r--src/plugins/Input/ffmpeg/CMakeLists.txt1
-rw-r--r--src/plugins/Input/mad/decoder_mad.cpp2
-rw-r--r--src/plugins/Input/mad/decodermadfactory.cpp11
-rw-r--r--src/plugins/Input/mad/decodermadfactory.h3
-rw-r--r--src/plugins/Input/vorbis/decoder_vorbis.cpp2
-rw-r--r--src/plugins/Input/vorbis/decodervorbisfactory.cpp21
-rw-r--r--src/plugins/Input/vorbis/decodervorbisfactory.h3
-rw-r--r--src/qmmp/decoder.cpp37
-rw-r--r--src/qmmp/decoder.h7
-rw-r--r--src/qmmp/decoderfactory.h3
-rw-r--r--src/qmmp/fileinfo.cpp16
-rw-r--r--src/qmmp/fileinfo.h10
-rw-r--r--src/qmmp/soundcore.cpp44
-rw-r--r--src/qmmp/soundcore.h7
-rw-r--r--src/qmmp/statehandler.cpp8
-rw-r--r--src/qmmp/statehandler.h17
-rw-r--r--src/ui/fileloader.cpp22
-rw-r--r--src/ui/fileloader.h50
-rw-r--r--src/ui/mainwindow.cpp2
-rw-r--r--src/ui/playlistitem.cpp22
-rw-r--r--src/ui/playlistitem.h3
-rw-r--r--src/ui/playlistmodel.cpp18
33 files changed, 962 insertions, 119 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 1e5300d19..1f330e4cb 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -86,6 +86,7 @@ PRINT_SUMMARY ("MOD support ......................." USE_MODPLUG MODPLUG_FOUND)
PRINT_SUMMARY ("Wave support ......................" USE_SNDFILE SNDFILE_FOUND)
PRINT_SUMMARY ("WavPack support ..................." USE_WAVPACK WAVPACK_FOUND)
PRINT_SUMMARY ("WMA support ......................." USE_FFMPEG FFMPEG_FOUND)
+PRINT_SUMMARY ("CUE sheet support ................." USE_CUE 1)
MESSAGE("")
MESSAGE("Output Plugins:")
diff --git a/src/plugins/Input/CMakeLists.txt b/src/plugins/Input/CMakeLists.txt
index 7a68dd8a3..3222be482 100644
--- a/src/plugins/Input/CMakeLists.txt
+++ b/src/plugins/Input/CMakeLists.txt
@@ -9,6 +9,7 @@ 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")
+SET(USE_CUE TRUE CACHE BOOL "enable/disable cue plugin")
pkg_check_modules(TAGLIB taglib)
@@ -43,3 +44,7 @@ ENDIF(USE_WAVPACK)
IF(USE_MODPLUG)
#add_subdirectory(modplug)
ENDIF(USE_MODPLUG)
+
+IF(USE_CUE)
+add_subdirectory(cue)
+ENDIF(USE_CUE)
diff --git a/src/plugins/Input/Input.pro b/src/plugins/Input/Input.pro
index 1035f6484..e40e324cd 100644
--- a/src/plugins/Input/Input.pro
+++ b/src/plugins/Input/Input.pro
@@ -1,6 +1,6 @@
include(../../../qmmp.pri)
-SUBDIRS += mad vorbis # sndfile wavpack
+SUBDIRS += mad vorbis cue # sndfile wavpack
TEMPLATE = subdirs
contains(CONFIG, MODPLUG_PLUGIN){
diff --git a/src/plugins/Input/cue/CMakeLists.txt b/src/plugins/Input/cue/CMakeLists.txt
new file mode 100644
index 000000000..b27497e1f
--- /dev/null
+++ b/src/plugins/Input/cue/CMakeLists.txt
@@ -0,0 +1,66 @@
+project(libcue)
+
+cmake_minimum_required(VERSION 2.4.7)
+
+if(COMMAND cmake_policy)
+cmake_policy(SET CMP0003 NEW)
+endif(COMMAND cmake_policy)
+
+
+# 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)
+
+
+SET(libcue_SRCS
+ decoder_cue.cpp
+ decodercuefactory.cpp
+# detailsdialog.cpp
+ cueparser.cpp
+)
+
+SET(libcue_MOC_HDRS
+ decodercuefactory.h
+ decoder_cue.h
+# detailsdialog.h
+ cueparser.h
+)
+
+#SET(libcue_RCCS translations/translations.qrc)
+
+QT4_ADD_RESOURCES(libcue_RCC_SRCS ${libcue_RCCS})
+
+QT4_WRAP_CPP(libcue_MOC_SRCS ${libcue_MOC_HDRS})
+
+# user interface
+
+
+#SET(libcue_UIS
+# detailsdialog.ui
+#)
+
+#QT4_WRAP_UI(libcue_UIS_H ${libcue_UIS})
+# Don't forget to include output directory, otherwise
+# the UI file won't be wrapped!
+include_directories(${CMAKE_CURRENT_BINARY_DIR})
+
+ADD_LIBRARY(cue SHARED ${libcue_SRCS} ${libcue_MOC_SRCS} ${libcue_RCC_SRCS})
+add_dependencies(cue qmmp)
+target_link_libraries(cue ${QT_LIBRARIES} -lqmmp)
+install(TARGETS cue DESTINATION ${LIB_DIR}/qmmp/Input)
+
diff --git a/src/plugins/Input/cue/cue.pro b/src/plugins/Input/cue/cue.pro
new file mode 100644
index 000000000..1c0771d5c
--- /dev/null
+++ b/src/plugins/Input/cue/cue.pro
@@ -0,0 +1,36 @@
+include(../../plugins.pri)
+
+#FORMS += detailsdialog.ui
+HEADERS += decodercuefactory.h \
+ cueparser.h \
+ decoder_cue.h
+SOURCES += decoder_cue.cpp \
+ decodercuefactory.cpp \
+ cueparser.cpp
+
+TARGET =$$PLUGINS_PREFIX/Input/cue
+QMAKE_CLEAN =$$PLUGINS_PREFIX/Input/libcue.so
+
+INCLUDEPATH += ../../../
+CONFIG += release \
+warn_on \
+plugin
+
+TEMPLATE = lib
+
+QMAKE_LIBDIR += ../../../../lib
+LIBS += -lqmmp -L/usr/lib
+
+#TRANSLATIONS = translations/cue_plugin_ru.ts
+# translations/cue_plugin_uk_UA.ts
+# translations/cue_plugin_zh_CN.ts
+# translations/cue_plugin_zh_TW.ts
+# translations/cue_plugin_cs.ts
+# translations/cue_plugin_de.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/cue/cueparser.cpp b/src/plugins/Input/cue/cueparser.cpp
new file mode 100644
index 000000000..cf79db5c2
--- /dev/null
+++ b/src/plugins/Input/cue/cueparser.cpp
@@ -0,0 +1,173 @@
+/***************************************************************************
+ * 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 <QRegExp>
+#include <QDir>
+
+#include <qmmp/decoder.h>
+
+#include "cueparser.h"
+
+CUEParser::CUEParser(const QString &fileName)
+{
+ QString album;
+ QFile file(fileName);
+ file.open(QIODevice::ReadOnly);
+
+ while (!file.atEnd())
+ {
+ QString line = file.readLine().trimmed();
+ QStringList words = splitLine(line);
+ if (words.size() < 2)
+ continue;
+
+ if (words[0] == "FILE")
+ {
+ //TODO check support
+ m_filePath = QUrl(fileName).path ();
+ m_filePath = QFileInfo(m_filePath).dir().filePath(words[1]);
+ }
+ else if (words[0] == "PERFORMER")
+ {
+ if (m_infoList.isEmpty())
+ continue;
+ else
+ m_infoList.last().setMetaData(Qmmp::ARTIST, words[1]);
+
+ }
+ else if (words[0] == "TITLE")
+ {
+ if (m_infoList.isEmpty())
+ album = words[1];
+ else
+ m_infoList.last().setMetaData(Qmmp::TITLE, words[1]);
+ }
+ else if (words[0] == "TRACK")
+ {
+ FileInfo info("cue://" + fileName + QString("#%1").arg(words[1].toInt()));
+ info.setMetaData(Qmmp::TRACK, words[1].toInt());
+ m_infoList << info;
+ m_offsets << 0;
+ }
+ else if (words[0] == "INDEX")
+ {
+ if (m_infoList.isEmpty())
+ continue;
+ m_infoList.last ().setLength(getLength(words[2]));
+ m_offsets.last() = getLength(words[2]);
+ }
+ }
+ //calculate length
+ for (int i = 0; i < m_infoList.size() - 1; ++i)
+ m_infoList[i].setLength(m_infoList[i+1].length()-m_infoList[i].length());
+ //calculate last item length
+ QList <FileInfo *> f_list;
+ f_list = Decoder::createPlayList(m_filePath);
+ qint64 l = f_list.isEmpty() ? 0 : f_list.at(0)->length();
+ if (l > m_infoList.last().length())
+ m_infoList.last().setLength(l - m_infoList.last().length());
+ else
+ m_infoList.last().setLength(0);
+
+ foreach(FileInfo info, m_infoList)
+ {
+ info.setMetaData(Qmmp::ALBUM, album);
+ }
+ file.close();
+}
+
+
+CUEParser::~CUEParser()
+{
+}
+
+QList<FileInfo*> CUEParser::createPlayList()
+{
+ QList<FileInfo*> list;
+ foreach(FileInfo info, m_infoList)
+ {
+ list << new FileInfo(info);
+ }
+ return list;
+}
+
+const QString CUEParser::filePath()
+{
+ return m_filePath;
+}
+
+qint64 CUEParser::offset(int track)
+{
+ return m_offsets.at(track - 1);
+}
+
+qint64 CUEParser::length(int track)
+{
+ return m_infoList.at(track - 1).length();
+}
+
+int CUEParser::count()
+{
+ return m_infoList.count();
+}
+
+FileInfo *CUEParser::info(int track)
+{
+ return &m_infoList[track - 1];
+}
+
+QStringList CUEParser::splitLine(const QString &line)
+{
+ //qDebug("row string = %s",qPrintable(line));
+ QStringList list;
+ QString buf = line.trimmed();
+ if (buf.isEmpty())
+ return list;
+ while (!buf.isEmpty())
+ {
+ //qDebug(qPrintable(buf));
+ if (buf.startsWith('"'))
+ {
+ int end = buf.indexOf('"',1);
+ list << buf.mid (1, end - 1);
+ buf.remove (0, end+1);
+ }
+ else
+ {
+ int end = buf.indexOf(' ', 0);
+ if (end < 0)
+ end = buf.size();
+ list << buf.mid (0, end);
+ buf.remove (0, end);
+ }
+ buf = buf.trimmed();
+ }
+ return list;
+}
+
+int CUEParser::getLength(const QString &str)
+{
+ QStringList list = str.split(":");
+ if (list.size() < 2)
+ return 0;
+ return list.at(0).toInt()*60 + list.at(1).toInt();
+}
diff --git a/src/plugins/Input/cue/cueparser.h b/src/plugins/Input/cue/cueparser.h
new file mode 100644
index 000000000..61807319a
--- /dev/null
+++ b/src/plugins/Input/cue/cueparser.h
@@ -0,0 +1,57 @@
+/***************************************************************************
+ * 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 CUEPARSER_H
+#define CUEPARSER_H
+
+#include <QList>
+#include <QMap>
+#include <QString>
+#include <QStringList>
+
+#include <qmmp/fileinfo.h>
+
+
+/**
+ @author Ilya Kotov <forkotov02@hotmail.ru>
+*/
+class CUEParser{
+public:
+ CUEParser(const QString &fileName);
+
+ ~CUEParser();
+
+ QList<FileInfo*> createPlayList();
+ const QString filePath();
+ qint64 offset(int track);
+ qint64 length(int track);
+ int count();
+ FileInfo *info(int track);
+
+private:
+ QList< QMap<int, int> > m_map;
+ QString m_filePath;
+ QList <FileInfo> m_infoList;
+ QList <int> m_offsets;
+ QStringList splitLine(const QString &line);
+ int getLength(const QString &str);
+
+};
+
+#endif
diff --git a/src/plugins/Input/cue/decoder_cue.cpp b/src/plugins/Input/cue/decoder_cue.cpp
new file mode 100644
index 000000000..d988d9aba
--- /dev/null
+++ b/src/plugins/Input/cue/decoder_cue.cpp
@@ -0,0 +1,208 @@
+/***************************************************************************
+ * 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 <qmmp/constants.h>
+#include <qmmp/buffer.h>
+#include <qmmp/output.h>
+#include <qmmp/recycler.h>
+#include <qmmp/fileinfo.h>
+#include <qmmp/decoderfactory.h>
+
+#include <QObject>
+#include <QFile>
+
+#include "cueparser.h"
+#include "decoder_cue.h"
+
+
+DecoderCUE::DecoderCUE(QObject *parent, DecoderFactory *d, const QString &url)
+ : Decoder(parent, d)
+{
+ path = url;
+ m_decoder = 0;
+ m_output2 = 0;
+ m_input2 = 0;
+}
+
+DecoderCUE::~DecoderCUE()
+{}
+
+bool DecoderCUE::initialize()
+{
+ CUEParser parser(QUrl(path).path());
+ int track = path.section("#", -1).toInt();
+ path = parser.filePath();
+ DecoderFactory *df = Decoder::findByPath(path);
+ if (df)
+ {
+ m_input2 = new QFile(path);
+ if (!m_input2->open(QIODevice::ReadOnly))
+ {
+ qDebug("DecoderCUE: cannot open input");
+ stop();
+ //m_handler->dispatch(Qmmp::NormalError);
+ return FALSE;
+ }
+ }
+ if (!df->properties().noOutput)
+ {
+ m_output2 = Output::create(this);
+ if (!m_output2)
+ {
+ qWarning("DecoderCUE: unable to create output");
+ //m_handler->dispatch(Qmmp::FatalError);
+ return FALSE;
+ }
+ if (!m_output2->initialize())
+ {
+ qWarning("SoundCore: unable to initialize output");
+ delete m_output2;
+ m_output2 = 0;
+ //m_handler->dispatch(Qmmp::FatalError);
+ return FALSE;
+ }
+ }
+ m_length = parser.length(track);
+ m_offset = parser.offset(track);
+ m_decoder = df->create(this, m_input2, m_output2, path);
+ CUEStateHandler *csh = new CUEStateHandler(this, m_offset, m_length);
+ m_decoder->setStateHandler(csh);
+ connect(csh, SIGNAL(finished()), SLOT(finish()));
+ connect(m_decoder, SIGNAL(playbackFinished()), SLOT(finish()));
+ if (m_output2)
+ m_output2->setStateHandler(m_decoder->stateHandler());
+ m_decoder->initialize();
+ m_decoder->seek(parser.offset(track));
+ if (m_output2)
+ m_output2->seek(parser.offset(track));
+
+ //send metadata
+ QMap<Qmmp::MetaData, QString> metaData = parser.info(track)->metaData();
+ StateHandler::instance()->dispatch(metaData);
+ return TRUE;
+}
+
+qint64 DecoderCUE::lengthInSeconds()
+{
+ return m_decoder ? m_length : 0;
+}
+
+void DecoderCUE::seek(qint64 pos)
+{
+ if (m_output2 && m_output2->isRunning())
+ {
+ m_output2->mutex()->lock ();
+ m_output2->seek(m_offset + pos);
+ m_output2->mutex()->unlock();
+ if (m_decoder && m_decoder->isRunning())
+ {
+ m_decoder->mutex()->lock ();
+ m_decoder->seek(m_offset + pos);
+ m_decoder->mutex()->unlock();
+ }
+ }
+ else if (m_decoder)
+ {
+ m_decoder->mutex()->lock ();
+ m_decoder->seek(m_offset + pos);
+ m_decoder->mutex()->unlock();
+ }
+}
+
+void DecoderCUE::stop()
+{
+ if (m_decoder /*&& m_decoder->isRunning()*/)
+ {
+ m_decoder->mutex()->lock ();
+ m_decoder->stop();
+ m_decoder->mutex()->unlock();
+ //m_decoder->stateHandler()->dispatch(Qmmp::Stopped);
+ }
+ if (m_output2)
+ {
+ m_output2->mutex()->lock ();
+ m_output2->stop();
+ m_output2->mutex()->unlock();
+ }
+
+ // wake up threads
+ if (m_decoder)
+ {
+ m_decoder->mutex()->lock ();
+ m_decoder->cond()->wakeAll();
+ m_decoder->mutex()->unlock();
+ }
+ if (m_output2)
+ {
+ m_output2->recycler()->mutex()->lock ();
+ m_output2->recycler()->cond()->wakeAll();
+ m_output2->recycler()->mutex()->unlock();
+ }
+ if (m_decoder)
+ m_decoder->wait();
+ if (m_output2)
+ m_output2->wait();
+
+ if (m_input2)
+ {
+ m_input2->deleteLater();
+ m_input2 = 0;
+ }
+}
+
+void DecoderCUE::run()
+{
+ m_decoder->start();
+ if (m_output2)
+ m_output2->start();
+}
+
+
+CUEStateHandler::CUEStateHandler(QObject *parent, qint64 offset, qint64 length): StateHandler(parent)
+{
+ m_offset = offset;
+ m_length2 = length;
+}
+
+CUEStateHandler::~CUEStateHandler(){};
+
+void CUEStateHandler::dispatch(qint64 elapsed,
+ qint64 totalTime,
+ int bitrate,
+ int frequency,
+ int precision,
+ int channels)
+{
+ Q_UNUSED(totalTime);
+ StateHandler::instance()->dispatch(elapsed - m_offset, m_length2, bitrate,
+ frequency, precision, channels);
+ if (elapsed - m_offset > m_length2)
+ emit finished();
+}
+
+void CUEStateHandler::dispatch(const QMap<Qmmp::MetaData, QString> &metaData)
+{
+ //ignore media file metadata
+}
+
+void CUEStateHandler::dispatch(const Qmmp::State &state)
+{
+ StateHandler::instance()->dispatch(state);
+}
diff --git a/src/plugins/Input/cue/decoder_cue.h b/src/plugins/Input/cue/decoder_cue.h
new file mode 100644
index 000000000..4e0775151
--- /dev/null
+++ b/src/plugins/Input/cue/decoder_cue.h
@@ -0,0 +1,82 @@
+/***************************************************************************
+ * 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_CUE_H
+#define DECODER_CUE_H
+
+#include <qmmp/decoder.h>
+#include <qmmp/statehandler.h>
+
+class Output;
+class QIDevice;
+//class CUEStateHandler;
+
+class DecoderCUE : public Decoder
+{
+ Q_OBJECT
+public:
+ DecoderCUE(QObject *, DecoderFactory *, const QString &url);
+ virtual ~DecoderCUE();
+
+ // Standard Decoder API
+ bool initialize();
+ qint64 lengthInSeconds();
+ void seek(qint64);
+ void stop();
+
+private:
+ // thread run function
+ void run();
+ QString path;
+ Decoder *m_decoder;
+ Output *m_output2;
+ QIODevice *m_input2;
+ qint64 m_length;
+ qint64 m_offset;
+};
+
+class CUEStateHandler : public StateHandler
+{
+ Q_OBJECT
+public:
+ CUEStateHandler(QObject *parent, qint64 offset, qint64 length);
+ virtual ~CUEStateHandler();
+
+ void dispatch(qint64 elapsed,
+ qint64 totalTime,
+ int bitrate,
+ int frequency,
+ int precision,
+ int channels);
+
+ void dispatch(const QMap<Qmmp::MetaData, QString> &metaData);
+
+ void dispatch(const Qmmp::State &state);
+
+signals:
+ void finished();
+
+private:
+ qint64 m_length2;
+ qint64 m_offset;
+
+};
+
+#endif // DECODER_CUE_H
diff --git a/src/plugins/Input/cue/decodercuefactory.cpp b/src/plugins/Input/cue/decodercuefactory.cpp
new file mode 100644
index 000000000..c87c4f4a6
--- /dev/null
+++ b/src/plugins/Input/cue/decodercuefactory.cpp
@@ -0,0 +1,91 @@
+/***************************************************************************
+ * 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 <QtGui>
+
+#include "decoder_cue.h"
+#include "cueparser.h"
+#include "decodercuefactory.h"
+
+
+// DecoderOggFactory
+
+bool DecoderCUEFactory::supports(const QString &source) const
+{
+ return source.right(4).toLower() == ".cue";
+}
+
+bool DecoderCUEFactory::canDecode(QIODevice *input) const
+{
+ return FALSE;
+}
+
+const DecoderProperties DecoderCUEFactory::properties() const
+{
+ DecoderProperties properties;
+ properties.name = tr("CUE Plugin");
+ properties.shortName = "cue";
+ properties.filter = "*.cue";
+ properties.description = tr("CUE Files");
+ //properties.contentType = "application/ogg;audio/x-vorbis+ogg";
+ properties.protocols = "cue";
+ properties.hasAbout = TRUE;
+ properties.hasSettings = FALSE;
+ properties.noInput = TRUE;
+ properties.noOutput = TRUE;
+ return properties;
+}
+
+Decoder *DecoderCUEFactory::create(QObject *parent, QIODevice *input,
+ Output *output, const QString &url)
+{
+ return new DecoderCUE(parent, this, url);
+}
+
+//FileInfo *DecoderCUEFactory::createFileInfo(const QString &source)
+QList<FileInfo *> DecoderCUEFactory::createPlayList(const QString &fileName)
+{
+ CUEParser parser(fileName);
+ return parser.createPlayList();
+}
+
+QObject* DecoderCUEFactory::showDetails(QWidget *parent, const QString &path)
+{
+ return 0;
+}
+
+void DecoderCUEFactory::showSettings(QWidget *)
+{}
+
+void DecoderCUEFactory::showAbout(QWidget *parent)
+{
+ QMessageBox::about (parent, tr("About CUE Audio Plugin"),
+ tr("Qmmp CUE Audio Plugin")+"\n"+
+ tr("Writen by: Ilya Kotov <forkotov02@hotmail.ru>"));
+}
+
+QTranslator *DecoderCUEFactory::createTranslator(QObject *parent)
+{
+ QTranslator *translator = new QTranslator(parent);
+ QString locale = QLocale::system().name();
+ translator->load(QString(":/cue_plugin_") + locale);
+ return translator;
+}
+
+Q_EXPORT_PLUGIN(DecoderCUEFactory)
diff --git a/src/plugins/Input/cue/decodercuefactory.h b/src/plugins/Input/cue/decodercuefactory.h
new file mode 100644
index 000000000..8cf38c6ad
--- /dev/null
+++ b/src/plugins/Input/cue/decodercuefactory.h
@@ -0,0 +1,51 @@
+/***************************************************************************
+ * Copyright (C) 2006-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 DECODERCUEFACTORY_H
+#define DECODERCUEFACTORY_H
+
+#include <QObject>
+#include <QString>
+#include <QIODevice>
+#include <QWidget>
+
+#include <qmmp/decoder.h>
+#include <qmmp/output.h>
+#include <qmmp/decoderfactory.h>
+#include <qmmp/fileinfo.h>
+
+class DecoderCUEFactory : 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 *, const QString &);
+ //FileInfo *createFileInfo(const QString &source);
+ QList<FileInfo *> createPlayList(const QString &fileName);
+ 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/ffmpeg/CMakeLists.txt b/src/plugins/Input/ffmpeg/CMakeLists.txt
index a97c78bad..a65f35963 100644
--- a/src/plugins/Input/ffmpeg/CMakeLists.txt
+++ b/src/plugins/Input/ffmpeg/CMakeLists.txt
@@ -100,6 +100,7 @@ include_directories(${CMAKE_CURRENT_BINARY_DIR})
IF(FFMPEG_FOUND)
ADD_LIBRARY(ffmpeg SHARED ${libffmpeg_SRCS} ${libffmpeg_MOC_SRCS} ${libffmpeg_UIS_H}
${libffmpeg_RCC_SRCS})
+add_dependencies(ffmpeg qmmp)
target_link_libraries(ffmpeg ${QT_LIBRARIES} -lqmmp ${FFMPEG_LDFLAGS} ${FFMPEG_CFLAGS})
install(TARGETS ffmpeg DESTINATION ${LIB_DIR}/qmmp/Input)
ENDIF(FFMPEG_FOUND)
diff --git a/src/plugins/Input/mad/decoder_mad.cpp b/src/plugins/Input/mad/decoder_mad.cpp
index 0eeb912cf..74b7c124a 100644
--- a/src/plugins/Input/mad/decoder_mad.cpp
+++ b/src/plugins/Input/mad/decoder_mad.cpp
@@ -110,7 +110,7 @@ bool DecoderMAD::initialize()
if (input()->isSequential ()) //for streams only
{
TagExtractor extractor(input());
- StateHandler::instance()->dispatch(extractor.id3v2tag());
+ stateHandler()->dispatch(extractor.id3v2tag());
}
mad_stream_init(&stream);
diff --git a/src/plugins/Input/mad/decodermadfactory.cpp b/src/plugins/Input/mad/decodermadfactory.cpp
index c41ab6fe9..ef8de8d45 100644
--- a/src/plugins/Input/mad/decodermadfactory.cpp
+++ b/src/plugins/Input/mad/decodermadfactory.cpp
@@ -99,11 +99,12 @@ Decoder *DecoderMADFactory::create(QObject *parent, QIODevice *input, Output *ou
return new DecoderMAD(parent, this, input, output);
}
-FileInfo *DecoderMADFactory::createFileInfo(const QString &source)
+//FileInfo *DecoderMADFactory::createFileInfo(const QString &source)
+QList<FileInfo *> DecoderMADFactory::createPlayList(const QString &fileName)
{
- FileInfo *info = new FileInfo();
+ FileInfo *info = new FileInfo(fileName);
TagLib::Tag *tag = 0;
- TagLib::MPEG::File fileRef(source.toLocal8Bit ());
+ TagLib::MPEG::File fileRef(fileName.toLocal8Bit ());
QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat);
settings.beginGroup("MAD");
@@ -183,7 +184,9 @@ FileInfo *DecoderMADFactory::createFileInfo(const QString &source)
}
if (fileRef.audioProperties())
info->setLength(fileRef.audioProperties()->length());
- return info;
+ QList <FileInfo*> list;
+ list << info;
+ return list;
}
QObject* DecoderMADFactory::showDetails(QWidget *parent, const QString &path)
diff --git a/src/plugins/Input/mad/decodermadfactory.h b/src/plugins/Input/mad/decodermadfactory.h
index b455f360e..a4d4d57ad 100644
--- a/src/plugins/Input/mad/decodermadfactory.h
+++ b/src/plugins/Input/mad/decodermadfactory.h
@@ -43,7 +43,8 @@ public:
bool canDecode(QIODevice *input) const;
const DecoderProperties properties() const;
Decoder *create(QObject *, QIODevice *, Output *, const QString &);
- FileInfo *createFileInfo(const QString &source);
+ //FileInfo *createFileInfo(const QString &source);
+ QList<FileInfo *> createPlayList(const QString &fileName);
QObject* showDetails(QWidget *parent, const QString &path);
void showSettings(QWidget *parent);
void showAbout(QWidget *parent);
diff --git a/src/plugins/Input/vorbis/decoder_vorbis.cpp b/src/plugins/Input/vorbis/decoder_vorbis.cpp
index 2d3500559..083ae1b30 100644
--- a/src/plugins/Input/vorbis/decoder_vorbis.cpp
+++ b/src/plugins/Input/vorbis/decoder_vorbis.cpp
@@ -292,7 +292,7 @@ void DecoderVorbis::updateTags()
+ strlen ("date="))));
}
- StateHandler::instance()->dispatch(metaData);
+ stateHandler()->dispatch(metaData);
}
void DecoderVorbis::run()
diff --git a/src/plugins/Input/vorbis/decodervorbisfactory.cpp b/src/plugins/Input/vorbis/decodervorbisfactory.cpp
index ceb0083ba..deca4f510 100644
--- a/src/plugins/Input/vorbis/decodervorbisfactory.cpp
+++ b/src/plugins/Input/vorbis/decodervorbisfactory.cpp
@@ -63,25 +63,26 @@ Decoder *DecoderVorbisFactory::create(QObject *parent, QIODevice *input,
return new DecoderVorbis(parent, this, input, output);
}
-FileInfo *DecoderVorbisFactory::createFileInfo(const QString &source)
+//FileInfo *DecoderVorbisFactory::createFileInfo(const QString &source)
+QList<FileInfo *> DecoderVorbisFactory::createPlayList(const QString &fileName)
{
- FileInfo *info = new FileInfo();
+ FileInfo *info = new FileInfo(fileName);
- TagLib::FileRef fileRef(source.toLocal8Bit ());
+ TagLib::FileRef fileRef(fileName.toLocal8Bit ());
TagLib::Tag *tag = fileRef.tag();
if (tag && !tag->isEmpty())
{
info->setMetaData(Qmmp::ALBUM,
- QString::fromUtf8(tag->album().toCString(TRUE)).trimmed());
+ QString::fromUtf8(tag->album().toCString(TRUE)).trimmed());
info->setMetaData(Qmmp::ARTIST,
- QString::fromUtf8(tag->artist().toCString(TRUE)).trimmed());
+ QString::fromUtf8(tag->artist().toCString(TRUE)).trimmed());
info->setMetaData(Qmmp::COMMENT,
- QString::fromUtf8(tag->comment().toCString(TRUE)).trimmed());
+ QString::fromUtf8(tag->comment().toCString(TRUE)).trimmed());
info->setMetaData(Qmmp::GENRE,
- QString::fromUtf8(tag->genre().toCString(TRUE)).trimmed());
+ QString::fromUtf8(tag->genre().toCString(TRUE)).trimmed());
info->setMetaData(Qmmp::TITLE,
- QString::fromUtf8(tag->title().toCString(TRUE)).trimmed());
+ QString::fromUtf8(tag->title().toCString(TRUE)).trimmed());
info->setMetaData(Qmmp::YEAR, tag->year());
info->setMetaData(Qmmp::TRACK, tag->track());
}
@@ -89,7 +90,9 @@ FileInfo *DecoderVorbisFactory::createFileInfo(const QString &source)
if (fileRef.audioProperties())
info->setLength(fileRef.audioProperties()->length());
- return info;
+ QList <FileInfo*> list;
+ list << info;
+ return list;
}
QObject* DecoderVorbisFactory::showDetails(QWidget *parent, const QString &path)
diff --git a/src/plugins/Input/vorbis/decodervorbisfactory.h b/src/plugins/Input/vorbis/decodervorbisfactory.h
index 811f2edc4..05c1d0ea6 100644
--- a/src/plugins/Input/vorbis/decodervorbisfactory.h
+++ b/src/plugins/Input/vorbis/decodervorbisfactory.h
@@ -44,7 +44,8 @@ public:
bool canDecode(QIODevice *input) const;
const DecoderProperties properties() const;
Decoder *create(QObject *, QIODevice *, Output *, const QString &);
- FileInfo *createFileInfo(const QString &source);
+ //FileInfo *createFileInfo(const QString &source);
+ QList<FileInfo *> createPlayList(const QString &fileName);
QObject* showDetails(QWidget *parent, const QString &path);
void showSettings(QWidget *parent);
void showAbout(QWidget *parent);
diff --git a/src/qmmp/decoder.cpp b/src/qmmp/decoder.cpp
index 25643e435..a4d739cf5 100644
--- a/src/qmmp/decoder.cpp
+++ b/src/qmmp/decoder.cpp
@@ -10,7 +10,6 @@
#include <QSettings>
#include <math.h>
-
#include "effect.h"
#include "effectfactory.h"
@@ -21,6 +20,7 @@
#include "decoderfactory.h"
#include "streamreader.h"
#include "volumecontrol.h"
+
extern "C"
{
#include "equ/iir.h"
@@ -32,13 +32,14 @@ Decoder::Decoder(QObject *parent, DecoderFactory *d, QIODevice *i, Output *o)
: QThread(parent), m_factory(d), m_input(i), m_output(o),m_eqInited(FALSE),
m_useEQ(FALSE)
{
- m_output->recycler()->clear();
+ if (m_output)
+ m_output->recycler()->clear();
int b[] = {0,0,0,0,0,0,0,0,0,0};
setEQ(b, 0);
qRegisterMetaType<Qmmp::State>("Qmmp::State");
blksize = Buffer::size();
m_effects = Effect::create(this);
- m_handler = StateHandler::instance();
+ m_handler = 0;
}
Decoder::~Decoder()
@@ -79,6 +80,11 @@ StateHandler *Decoder::stateHandler()
return m_handler;
}
+void Decoder::setStateHandler(StateHandler *handler)
+{
+ m_handler = handler;
+}
+
void Decoder::setEQ(int bands[10], int preamp)
{
set_preamp(0, 1.0 + 0.0932471 *preamp + 0.00279033 * preamp * preamp);
@@ -356,6 +362,8 @@ DecoderFactory *Decoder::findByContent(QIODevice *input)
DecoderFactory *Decoder::findByURL(const QUrl &url)
{
+ qDebug("url.scheme() %s", qPrintable(url.scheme()));
+ qDebug("url.path() = %s", qPrintable(url.path()));
checkFactories();
foreach(DecoderFactory *fact, *m_factories)
{
@@ -400,7 +408,7 @@ bool Decoder::isEnabled(DecoderFactory* factory)
return !disabledList.contains(name);
}
-FileInfo *Decoder::createFileInfo(const QString &fileName)
+/*FileInfo *Decoder::createFileInfo(const QString &fileName)
{
DecoderFactory *fact = Decoder::findByPath(fileName);
if (fact && QFile::exists(fileName))
@@ -411,6 +419,27 @@ FileInfo *Decoder::createFileInfo(const QString &fileName)
return fact->createFileInfo(fileName);
}
return 0;
+}*/
+
+QList <FileInfo *> Decoder::createPlayList(const QString &fileName)
+{
+ QList <FileInfo *> list;
+ if (QFile::exists(fileName)) //is it file?
+ {
+ DecoderFactory *fact = Decoder::findByPath(fileName);
+ if (fact)
+ list << fact->createPlayList(fileName);
+ }
+ else
+ //TODO do this according supported protocols
+ list << new FileInfo(fileName); //create empty FileInfo for stream
+ //append path if it is empty
+ foreach(FileInfo *info, list)
+ {
+ if (info->path().isEmpty())
+ info->setPath(fileName);
+ }
+ return list;
}
QStringList Decoder::filters()
diff --git a/src/qmmp/decoder.h b/src/qmmp/decoder.h
index feaa5dd85..42b2a8639 100644
--- a/src/qmmp/decoder.h
+++ b/src/qmmp/decoder.h
@@ -14,6 +14,7 @@
#include <QObject>
#include <QStringList>
#include <QUrl>
+#include <QList>
#include "fileinfo.h"
@@ -53,6 +54,7 @@ public:
QWaitCondition *cond();
StateHandler *stateHandler();
+ void setStateHandler(StateHandler *handler);
void setEQ(int bands[10], int preamp);
void setEQEnabled(bool on);
@@ -64,7 +66,9 @@ public:
static DecoderFactory *findByMime(const QString&);
static DecoderFactory *findByContent(QIODevice *);
static DecoderFactory *findByURL(const QUrl &url);
- static FileInfo *createFileInfo(const QString &fileName);
+ //static FileInfo *createFileInfo(const QString &fileName);
+ static QList <FileInfo *> createPlayList(const QString &fileName);
+ //static QList <FileInfo *> createPlayList(const QStringList &fileList);
static QStringList filters();
static QStringList nameFilters();
static QList<DecoderFactory*> *factories();
@@ -78,6 +82,7 @@ signals:
protected:
void configure(quint32 srate, int chan, int bps);
qint64 produceSound(char *data, qint64 size, quint32 brate, int chan);
+protected slots:
void finish();
private:
diff --git a/src/qmmp/decoderfactory.h b/src/qmmp/decoderfactory.h
index 0bfb6d0ef..80b2008ee 100644
--- a/src/qmmp/decoderfactory.h
+++ b/src/qmmp/decoderfactory.h
@@ -64,7 +64,8 @@ public:
virtual const DecoderProperties properties() const = 0;
virtual Decoder *create(QObject *, QIODevice *input = 0,
Output *output = 0, const QString &path = QString()) = 0;
- virtual FileInfo *createFileInfo(const QString &source) = 0;
+ //virtual FileInfo *createFileInfo(const QString &source) = 0;
+ virtual QList<FileInfo *> createPlayList(const QString &fileName) = 0;
virtual QObject* showDetails(QWidget *parent, const QString &path) = 0;
virtual void showSettings(QWidget *parent) = 0;
virtual void showAbout(QWidget *parent) = 0;
diff --git a/src/qmmp/fileinfo.cpp b/src/qmmp/fileinfo.cpp
index 055cec343..593b5203c 100644
--- a/src/qmmp/fileinfo.cpp
+++ b/src/qmmp/fileinfo.cpp
@@ -19,10 +19,10 @@
***************************************************************************/
#include "fileinfo.h"
-FileInfo::FileInfo()
+FileInfo::FileInfo(const QString &path)
{
+ m_path = path;
m_length = 0;
- m_count = 1;
}
FileInfo::FileInfo(const FileInfo &other)
@@ -37,14 +37,14 @@ void FileInfo::operator=(const FileInfo &info)
{
setLength(info.length());
setMetaData(info.metaData());
- setUrl(info.url());
+ setPath(info.path());
}
bool FileInfo::operator==(const FileInfo &info)
{
return metaData () == info.metaData () &&
length () == info.length ();
- url() == info.url();
+ path() == info.path();
}
bool FileInfo::operator!=(const FileInfo &info)
@@ -77,9 +77,9 @@ bool FileInfo::isEmpty() const
return m_metaData.isEmpty(); //TODO add correct test
}
-const QUrl FileInfo::url() const
+const QString FileInfo::path() const
{
- return m_url;
+ return m_path;
}
void FileInfo::setLength(qint64 length)
@@ -97,7 +97,7 @@ void FileInfo::setMetaData(Qmmp::MetaData key, int value)
m_metaData.insert(key, QString::number(value));
}
-void FileInfo::setUrl(const QUrl &url)
+void FileInfo::setPath(const QString &path)
{
- m_url = url;
+ m_path = path;
}
diff --git a/src/qmmp/fileinfo.h b/src/qmmp/fileinfo.h
index a2e70188e..c01ac4306 100644
--- a/src/qmmp/fileinfo.h
+++ b/src/qmmp/fileinfo.h
@@ -32,7 +32,7 @@
class FileInfo
{
public:
- FileInfo();
+ FileInfo(const QString &path = QString());
FileInfo(const FileInfo &other);
~FileInfo();
@@ -45,20 +45,18 @@ public:
const QString metaData (Qmmp::MetaData key) const;
const QMap<Qmmp::MetaData, QString> metaData () const;
bool isEmpty() const;
- const QUrl url() const;
- int count();
+ const QString path() const;
void setLength(qint64 length);
void setMetaData(Qmmp::MetaData key, const QString &value);
void setMetaData(Qmmp::MetaData key, int value);
void setMetaData(const QMap <Qmmp::MetaData, QString> &metaData);
- void setUrl(const QUrl &url);
+ void setPath(const QString &path);
private:
QMap <Qmmp::MetaData, QString> m_metaData;
qint64 m_length;
- QUrl m_url;
- int m_count;
+ QString m_path;
QList<QMap<int, int> > map;
};
diff --git a/src/qmmp/soundcore.cpp b/src/qmmp/soundcore.cpp
index 7cb59cb05..7742ca92d 100644
--- a/src/qmmp/soundcore.cpp
+++ b/src/qmmp/soundcore.cpp
@@ -54,6 +54,8 @@ SoundCore::SoundCore(QObject *parent)
for (int i = 1; i < 10; ++i)
m_bands[i] = 0;
m_handler = new StateHandler(this);
+ //StateHandler::instance() = 0;
+ //StateHandler::m_instance = m_handler;
connect(m_handler, SIGNAL(elapsedChanged(qint64)), SIGNAL(elapsedChanged(qint64)));
connect(m_handler, SIGNAL(bitrateChanged(int)), SIGNAL(bitrateChanged(int)));
connect(m_handler, SIGNAL(frequencyChanged(int)), SIGNAL(frequencyChanged(int)));
@@ -74,23 +76,25 @@ SoundCore::~SoundCore()
bool SoundCore::play(const QString &source)
{
stop();
+ m_source = source;
if (m_handler->state() != Qmmp::Stopped) //clear error state
m_handler->dispatch(Qmmp::Stopped);
+ QUrl url;
if (QFile::exists(source)) //local file
- m_url = QUrl::fromLocalFile(source);
+ url = QUrl::fromLocalFile(source);
else
- m_url = source;
+ url = source;
- m_factory = Decoder::findByURL(m_url);
+ m_factory = Decoder::findByURL(url);
if (m_factory)
return decode();
- if (m_url.scheme() == "file")
+ if (url.scheme() == "file")
{
- if ((m_factory = Decoder::findByPath(m_url.path())))
+ if ((m_factory = Decoder::findByPath(m_source)))
{
- m_input = new QFile(m_url.path());
+ m_input = new QFile(m_source);
if (!m_input->open(QIODevice::ReadOnly))
{
qDebug("SoundCore: cannot open input");
@@ -98,9 +102,13 @@ bool SoundCore::play(const QString &source)
m_handler->dispatch(Qmmp::NormalError);
return FALSE;
}
- FileInfo *finfo = m_factory->createFileInfo(m_url.toLocalFile ());
- m_handler->dispatch(finfo->metaData());
- delete finfo;
+ QList <FileInfo *> list = m_factory->createPlayList(url.toLocalFile ());
+ if (!list.isEmpty())
+ {
+ m_handler->dispatch(list[0]->metaData());
+ while (!list.isEmpty())
+ delete list.takeFirst();
+ }
return decode();
}
else
@@ -111,7 +119,7 @@ bool SoundCore::play(const QString &source)
return FALSE;
}
}
- if (m_url.scheme() == "http")
+ if (url.scheme() == "http")
{
m_input = new StreamReader(source, this);
connect(m_input, SIGNAL(bufferingProgress(int)), SIGNAL(bufferingProgress(int)));
@@ -128,8 +136,8 @@ bool SoundCore::play(const QString &source)
void SoundCore::stop()
{
m_factory = 0;
- m_url.clear();
- if (m_decoder && m_decoder->isRunning())
+ m_source.clear();
+ if (m_decoder /*&& m_decoder->isRunning()*/)
{
m_decoder->mutex()->lock ();
m_decoder->stop();
@@ -224,6 +232,12 @@ void SoundCore::seek(qint64 pos)
m_decoder->mutex()->unlock();
}
}
+ else if (m_decoder)
+ {
+ m_decoder->mutex()->lock ();
+ m_decoder->seek(pos);
+ m_decoder->mutex()->unlock();
+ }
}
qint64 SoundCore::length() const
@@ -363,7 +377,8 @@ bool SoundCore::decode()
return FALSE;
}
}
- m_decoder = m_factory->create(this, m_input, m_output, m_url.path());
+ m_decoder = m_factory->create(this, m_input, m_output, m_source);
+ m_decoder->setStateHandler(m_handler);
if (!m_decoder)
{
qWarning("SoundCore: unsupported fileformat");
@@ -379,7 +394,8 @@ bool SoundCore::decode()
if (m_decoder->initialize())
{
- m_output->start();
+ if (m_output)
+ m_output->start();
m_decoder->start();
return TRUE;
}
diff --git a/src/qmmp/soundcore.h b/src/qmmp/soundcore.h
index b24dd886e..a4d5819d7 100644
--- a/src/qmmp/soundcore.h
+++ b/src/qmmp/soundcore.h
@@ -82,13 +82,12 @@ public:
QString metaData(Qmmp::MetaData key);
-
-
/*!
* Returns a pointer to the SoundCore instance.
*/
static SoundCore* instance();
+
public slots:
void setSoftwareVolume(bool);
@@ -148,7 +147,8 @@ private slots:
private:
Decoder* m_decoder;
DecoderFactory* m_factory;
- QUrl m_url;
+ //QUrl m_url;
+ QString m_source;
Output* m_output;
QIODevice* m_input;
uint m_error;
@@ -160,7 +160,6 @@ private:
int m_bands[10];
Visual *m_vis;
QList <Visual*> m_visuals;
- QString m_source;
QWidget *m_parentWidget;
static SoundCore* m_instance;
StateHandler *m_handler;
diff --git a/src/qmmp/statehandler.cpp b/src/qmmp/statehandler.cpp
index eceed5f76..20489f941 100644
--- a/src/qmmp/statehandler.cpp
+++ b/src/qmmp/statehandler.cpp
@@ -28,7 +28,8 @@ StateHandler* StateHandler::m_instance = 0;
StateHandler::StateHandler(QObject *parent)
: QObject(parent)
{
- m_instance = this;
+ if (!m_instance)
+ m_instance = this;
m_elapsed = -1;
m_bitrate = 0;
m_frequency = 0;
@@ -41,7 +42,8 @@ StateHandler::StateHandler(QObject *parent)
StateHandler::~StateHandler()
{
- m_instance = 0;
+ if (m_instance == this)
+ m_instance = 0;
}
@@ -127,7 +129,7 @@ void StateHandler::dispatch(const Qmmp::State &state)
m_metaData.clear();
}
emit stateChanged(state);
- if(m_state == Qmmp::Playing && m_sendMeta)
+ if (m_state == Qmmp::Playing && m_sendMeta)
{
m_sendMeta = FALSE;
emit metaDataChanged ();
diff --git a/src/qmmp/statehandler.h b/src/qmmp/statehandler.h
index 6be225b4e..702a24c1b 100644
--- a/src/qmmp/statehandler.h
+++ b/src/qmmp/statehandler.h
@@ -37,16 +37,16 @@ public:
~StateHandler();
- void dispatch(qint64 elapsed,
- qint64 totalTime,
- int bitrate,
- int frequency,
- int precision,
- int channels);
+ virtual void dispatch(qint64 elapsed,
+ qint64 totalTime,
+ int bitrate,
+ int frequency,
+ int precision,
+ int channels);
- void dispatch(const QMap<Qmmp::MetaData, QString> &metaData);
+ virtual void dispatch(const QMap<Qmmp::MetaData, QString> &metaData);
- void dispatch(const Qmmp::State &state);
+ virtual void dispatch(const Qmmp::State &state);
qint64 elapsed();
int bitrate();
@@ -80,7 +80,6 @@ private:
Qmmp::State m_state;
QMutex m_mutex;
bool m_sendMeta;
-
};
#endif
diff --git a/src/ui/fileloader.cpp b/src/ui/fileloader.cpp
index 6cf71e3b2..ce5ccb56c 100644
--- a/src/ui/fileloader.cpp
+++ b/src/ui/fileloader.cpp
@@ -43,8 +43,13 @@ void FileLoader::addFiles(const QStringList &files)
foreach(QString s, files)
{
- if (s.startsWith("http://") || Decoder::supports(s))
- emit newPlayListItem(new PlayListItem(s));
+ /*if (s.startsWith("http://") || Decoder::supports(s))
+ {*/
+ //emit newPlayListItem(new PlayListItem(s));
+ QList <FileInfo *> playList = Decoder::createPlayList(s);
+ foreach(FileInfo *info, playList)
+ emit newPlayListItem(new PlayListItem(info));
+ //}
if (m_finished) return;
}
}
@@ -52,6 +57,7 @@ void FileLoader::addFiles(const QStringList &files)
void FileLoader::addDirectory(const QString& s)
{
+ QList <FileInfo *> playList;
QDir dir(s);
dir.setFilter(QDir::Files | QDir::Hidden | QDir::NoSymLinks);
dir.setSorting(QDir::Name);
@@ -62,8 +68,13 @@ void FileLoader::addDirectory(const QString& s)
QString suff = fileInfo.completeSuffix();
list << fileInfo;
- if (Decoder::supports(fileInfo.absoluteFilePath ()))
- emit newPlayListItem(new PlayListItem(fileInfo.absoluteFilePath ()));
+ /*if (Decoder::supports(fileInfo.absoluteFilePath ()))
+ {*/
+ playList = Decoder::createPlayList(fileInfo.absoluteFilePath ());
+ foreach(FileInfo *info, playList)
+ emit newPlayListItem(new PlayListItem(info));
+ //emit newPlayListItem(new PlayListItem(fileInfo.absoluteFilePath ()));
+ //}
if (m_finished) return;
}
dir.setFilter(QDir::Dirs | QDir::NoDotAndDotDot);
@@ -79,7 +90,6 @@ void FileLoader::addDirectory(const QString& s)
}
}
-
void FileLoader::run()
{
if (!m_files_to_load.isEmpty())
@@ -88,8 +98,6 @@ void FileLoader::run()
addDirectory(m_directory);
}
-
-
void FileLoader::setFilesToLoad(const QStringList & l)
{
m_files_to_load = l;
diff --git a/src/ui/fileloader.h b/src/ui/fileloader.h
index a67ec3567..d2dcc0748 100644
--- a/src/ui/fileloader.h
+++ b/src/ui/fileloader.h
@@ -27,46 +27,46 @@
class PlayListItem;
/*!
- * This class represents fileloader object that
+ * This class represents fileloader object that
* processes file list in separate thread and emits
* \b newPlayListItem(PlayListItem*) signal for every newly
* created media file.
- @author Ilya Kotov <forkotov02@hotmail.ru>
+ @author Ilya Kotov <forkotov02@hotmail.ru>
*/
class FileLoader : public QThread
{
-Q_OBJECT
+ Q_OBJECT
public:
FileLoader(QObject *parent = 0);
~FileLoader();
- virtual void run();
-
- /*!
- * Call this method when you want to notify the thread about finishing
- */
- void finish();
-
- /*!
- * Sets filelist to load( directory to load will be cleaned )
- */
- void setFilesToLoad(const QStringList&);
-
- /*!
- * Sets directory to load( filelist to load will be cleaned )
- */
- void setDirectoryToLoad(const QString&);
+ virtual void run();
+
+ /*!
+ * Call this method when you want to notify the thread about finishing
+ */
+ void finish();
+
+ /*!
+ * Sets filelist to load( directory to load will be cleaned )
+ */
+ void setFilesToLoad(const QStringList&);
+
+ /*!
+ * Sets directory to load( filelist to load will be cleaned )
+ */
+ void setDirectoryToLoad(const QString&);
signals:
- void newPlayListItem(PlayListItem*);
+ void newPlayListItem(PlayListItem*);
protected:
- void addFiles(const QStringList &files);
- void addDirectory(const QString& s);
+ void addFiles(const QStringList &files);
+ void addDirectory(const QString& s);
private:
QFileInfoList list;
QStringList m_filters;
- QStringList m_files_to_load;
- QString m_directory;
- bool m_finished;
+ QStringList m_files_to_load;
+ QString m_directory;
+ bool m_finished;
};
#endif
diff --git a/src/ui/mainwindow.cpp b/src/ui/mainwindow.cpp
index d2e50a98c..1cd0a26d3 100644
--- a/src/ui/mainwindow.cpp
+++ b/src/ui/mainwindow.cpp
@@ -181,7 +181,7 @@ void MainWindow::play()
return;
m_equalizer->loadPreset(m_playListModel->currentItem()->fileName());
- m_playListModel->currentItem()->updateTags();
+ //m_playListModel->currentItem()->updateTags();
m_playlist->listWidget()->updateList();
QString s = m_playListModel->currentItem()->path();
if (s.isEmpty())
diff --git a/src/ui/playlistitem.cpp b/src/ui/playlistitem.cpp
index b5321c8ca..738f8fdae 100644
--- a/src/ui/playlistitem.cpp
+++ b/src/ui/playlistitem.cpp
@@ -29,13 +29,14 @@ PlayListItem::PlayListItem() : SongInfo(), m_flag(FREE)
m_info = 0;
}
-PlayListItem::PlayListItem(const QString& path) : SongInfo(), m_flag(FREE)
+//PlayListItem::PlayListItem(const QString& path) : SongInfo(), m_flag(FREE)
+PlayListItem::PlayListItem(FileInfo *info) : SongInfo(), m_flag(FREE)
{
m_selected = FALSE;
m_current = FALSE;
- m_info = 0;
- setValue(SongInfo::PATH, path);
- setValue(SongInfo::STREAM, path.startsWith("http://")); //TODO do this inside SongInfo
+ m_info = info;
+ setValue(SongInfo::PATH, info->path()); //TODO path?
+ setValue(SongInfo::STREAM, path().startsWith("http://")); //TODO do this inside SongInfo
QSettings settings ( QDir::homePath() +"/.qmmp/qmmprc", QSettings::IniFormat );
m_use_meta = settings.value ("PlayList/load_metadata", TRUE).toBool();
//format
@@ -45,15 +46,15 @@ PlayListItem::PlayListItem(const QString& path) : SongInfo(), m_flag(FREE)
m_convertTwenty = settings.value ("PlayList/convert_twenty", TRUE).toBool();
m_fullStreamPath = settings.value ("PlayList/full_stream_path", FALSE).toBool();
- if (m_use_meta && !path.startsWith("http://"))
+ if (m_use_meta && !path().startsWith("http://"))
{
- m_info = Decoder::createFileInfo(path);
+ //m_info = Decoder::createFileInfo(path);
readMetadata();
}
- else if (path.startsWith("http://") && m_fullStreamPath)
- m_title = path;
+ else if (path().startsWith("http://") && m_fullStreamPath)
+ m_title = path();
else
- m_title = path.split('/',QString::SkipEmptyParts).takeLast ();
+ m_title = path().split('/',QString::SkipEmptyParts).takeLast ();
}
PlayListItem::~PlayListItem()
@@ -111,7 +112,8 @@ void PlayListItem::updateTags()
delete m_info;
m_info = 0;
}
- m_info = Decoder::createFileInfo(path());
+ //m_info = Decoder::createFileInfo(path());
+ m_info = Decoder::createPlayList(path()).at(0);
readMetadata();
}
diff --git a/src/ui/playlistitem.h b/src/ui/playlistitem.h
index 818bc7eeb..29181dcce 100644
--- a/src/ui/playlistitem.h
+++ b/src/ui/playlistitem.h
@@ -39,7 +39,8 @@ public:
*/
enum FLAGS{FREE = 0,EDITING,SCHEDULED_FOR_DELETION};
PlayListItem();
- PlayListItem(const QString& path);
+ //PlayListItem(const QString& path);
+ PlayListItem(FileInfo *info);
~PlayListItem();
diff --git a/src/ui/playlistmodel.cpp b/src/ui/playlistmodel.cpp
index 327b88598..1a92d0bc3 100644
--- a/src/ui/playlistmodel.cpp
+++ b/src/ui/playlistmodel.cpp
@@ -314,10 +314,10 @@ void PlayListModel::showDetails()
str.append(tr("Album:") + " %4\n");
str.append(tr("Comment:") + " %5");
str = str.arg(item->path())
- .arg(item->title().isEmpty() ? item->text() : item->title())
- .arg(item->artist())
- .arg(item->album())
- .arg(item->comment());
+ .arg(item->title().isEmpty() ? item->text() : item->title())
+ .arg(item->artist())
+ .arg(item->album())
+ .arg(item->comment());
QMessageBox::information(0, m_items.at (i)->path(), str);
return;
}
@@ -365,7 +365,8 @@ void PlayListModel::readSettings()
for (int i = 0;i < preload;i++)
{
- load(new PlayListItem(files.takeAt(0)));
+ //TODO load tags from cache
+ load(new PlayListItem(Decoder::createPlayList(files.takeAt(0)).at(0)));
}
if (files.isEmpty())
@@ -398,10 +399,13 @@ void PlayListModel::addFile(const QString& path)
{
if (path.isEmpty ())
return;
- if (path.startsWith("http://"))
+ /*if (path.startsWith("http://"))
load(new PlayListItem(path));
else if (Decoder::supports(path))
- load(new PlayListItem(path));
+ load(new PlayListItem(path));*/
+ QList <FileInfo *> playList = Decoder::createPlayList(path);
+ foreach(FileInfo *info, playList)
+ emit load(new PlayListItem(info));
m_play_state->prepare();
}