diff options
| author | trialuser02 <trialuser02@90c681e8-e032-0410-971d-27865f9a5e38> | 2009-09-15 15:54:18 +0000 |
|---|---|---|
| committer | trialuser02 <trialuser02@90c681e8-e032-0410-971d-27865f9a5e38> | 2009-09-15 15:54:18 +0000 |
| commit | 8ba3c4bc2f133794b60d8224ef1d844fb6903344 (patch) | |
| tree | 816e56a4f42d32266518c1ecc3cbba78987f8bfa /src | |
| parent | 095abc2e238556b3b89f55a6c7885450e3e3385b (diff) | |
| download | qmmp-8ba3c4bc2f133794b60d8224ef1d844fb6903344.tar.gz qmmp-8ba3c4bc2f133794b60d8224ef1d844fb6903344.tar.bz2 qmmp-8ba3c4bc2f133794b60d8224ef1d844fb6903344.zip | |
fixed some bugs, removed unused code
git-svn-id: http://svn.code.sf.net/p/qmmp-dev/code/trunk/qmmp@1222 90c681e8-e032-0410-971d-27865f9a5e38
Diffstat (limited to 'src')
| -rw-r--r-- | src/plugins/Input/cue/decoder_cue.cpp | 6 | ||||
| -rw-r--r-- | src/plugins/Input/cue/decoder_cue.h | 2 | ||||
| -rw-r--r-- | src/plugins/Input/cue/decodercuefactory.cpp | 7 | ||||
| -rw-r--r-- | src/plugins/Input/cue/decodercuefactory.h | 2 | ||||
| -rw-r--r-- | src/plugins/Input/mad/decoder_mad.h | 3 | ||||
| -rw-r--r-- | src/plugins/Input/mad/decodermadfactory.cpp | 2 | ||||
| -rw-r--r-- | src/plugins/Input/mad/decodermadfactory.h | 2 | ||||
| -rw-r--r-- | src/plugins/Input/mad/translations/mad_plugin_ru.ts | 26 | ||||
| -rw-r--r-- | src/qmmp/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | src/qmmp/abstractengine.h | 4 | ||||
| -rw-r--r-- | src/qmmp/audioparameters.cpp | 2 | ||||
| -rw-r--r-- | src/qmmp/decoder.cpp | 6 | ||||
| -rw-r--r-- | src/qmmp/decoderfactory.h | 4 | ||||
| -rw-r--r-- | src/qmmp/inputsource.cpp | 72 | ||||
| -rw-r--r-- | src/qmmp/inputsource.h | 46 | ||||
| -rw-r--r-- | src/qmmp/output.cpp | 6 | ||||
| -rw-r--r-- | src/qmmp/qmmp.pro | 6 | ||||
| -rw-r--r-- | src/qmmp/qmmpaudioengine.cpp | 242 | ||||
| -rw-r--r-- | src/qmmp/qmmpaudioengine.h | 15 | ||||
| -rw-r--r-- | src/qmmp/soundcore.cpp | 91 | ||||
| -rw-r--r-- | src/qmmp/soundcore.h | 2 | ||||
| -rw-r--r-- | src/qmmpui/mediaplayer.cpp | 9 | ||||
| -rw-r--r-- | src/qmmpui/translations/libqmmpui_ru.ts | 38 |
23 files changed, 347 insertions, 248 deletions
diff --git a/src/plugins/Input/cue/decoder_cue.cpp b/src/plugins/Input/cue/decoder_cue.cpp index 8ee786105..944c9911a 100644 --- a/src/plugins/Input/cue/decoder_cue.cpp +++ b/src/plugins/Input/cue/decoder_cue.cpp @@ -32,8 +32,8 @@ #include "decoder_cue.h" -DecoderCUE::DecoderCUE(const QString &url, QIODevice *input) - : Decoder(input) +DecoderCUE::DecoderCUE(const QString &url) + : Decoder() { m_path = url; m_decoder = 0; @@ -73,7 +73,7 @@ bool DecoderCUE::initialize() m_length = parser.length(track); m_offset = parser.offset(track); - m_decoder = df->create(new QFile(m_path), m_path); + m_decoder = df->create(m_path, new QFile(m_path)); if(!m_decoder->initialize()) { qWarning("DecoderCUE: invalid audio file"); diff --git a/src/plugins/Input/cue/decoder_cue.h b/src/plugins/Input/cue/decoder_cue.h index 1f641574f..ce3bcb4b5 100644 --- a/src/plugins/Input/cue/decoder_cue.h +++ b/src/plugins/Input/cue/decoder_cue.h @@ -30,7 +30,7 @@ class QIDevice; class DecoderCUE : public Decoder { public: - DecoderCUE(const QString &url, QIODevice *input); + DecoderCUE(const QString &url); virtual ~DecoderCUE(); // Standard Decoder API diff --git a/src/plugins/Input/cue/decodercuefactory.cpp b/src/plugins/Input/cue/decodercuefactory.cpp index a25e930f7..5b7a9a716 100644 --- a/src/plugins/Input/cue/decodercuefactory.cpp +++ b/src/plugins/Input/cue/decodercuefactory.cpp @@ -53,11 +53,10 @@ const DecoderProperties DecoderCUEFactory::properties() const return properties; } -Decoder *DecoderCUEFactory::create(QIODevice *input, const QString &path) +Decoder *DecoderCUEFactory::create(const QString &path, QIODevice *input) { - //Q_UNUSED(input); - //Q_UNUSED(output); - return new DecoderCUE(path, input); + Q_UNUSED(input); + return new DecoderCUE(path); } QList<FileInfo *> DecoderCUEFactory::createPlayList(const QString &fileName, bool useMetaData) diff --git a/src/plugins/Input/cue/decodercuefactory.h b/src/plugins/Input/cue/decodercuefactory.h index d24108369..451ae5f4f 100644 --- a/src/plugins/Input/cue/decodercuefactory.h +++ b/src/plugins/Input/cue/decodercuefactory.h @@ -40,7 +40,7 @@ public: bool supports(const QString &source) const; bool canDecode(QIODevice *input) const; const DecoderProperties properties() const; - Decoder *create(QIODevice *, const QString &); + Decoder *create(const QString &, QIODevice *); QList<FileInfo *> createPlayList(const QString &fileName, bool useMetaData); MetaDataModel* createMetaDataModel(const QString &path, QObject *parent = 0); void showSettings(QWidget *parent); diff --git a/src/plugins/Input/mad/decoder_mad.h b/src/plugins/Input/mad/decoder_mad.h index 68fc35538..c78e3f8c8 100644 --- a/src/plugins/Input/mad/decoder_mad.h +++ b/src/plugins/Input/mad/decoder_mad.h @@ -29,11 +29,10 @@ public: bool initialize(); qint64 totalTime(); int bitrate(); - -private: qint64 read(char *data, qint64 size); void seek(qint64); +private: // helper functions qint64 madOutput(char *data, qint64 size); bool fillBuffer(); diff --git a/src/plugins/Input/mad/decodermadfactory.cpp b/src/plugins/Input/mad/decodermadfactory.cpp index 47de2e828..11009d617 100644 --- a/src/plugins/Input/mad/decodermadfactory.cpp +++ b/src/plugins/Input/mad/decodermadfactory.cpp @@ -94,7 +94,7 @@ const DecoderProperties DecoderMADFactory::properties() const return properties; } -Decoder *DecoderMADFactory::create(QIODevice *input, const QString &) +Decoder *DecoderMADFactory::create(const QString&, QIODevice *input) { return new DecoderMAD(input); } diff --git a/src/plugins/Input/mad/decodermadfactory.h b/src/plugins/Input/mad/decodermadfactory.h index 6107e56f0..a4e18c8f4 100644 --- a/src/plugins/Input/mad/decodermadfactory.h +++ b/src/plugins/Input/mad/decodermadfactory.h @@ -43,7 +43,7 @@ public: bool supports(const QString &source) const; bool canDecode(QIODevice *input) const; const DecoderProperties properties() const; - Decoder *create(QIODevice *, const QString &); + Decoder *create(const QString &path, QIODevice *input); QList<FileInfo *> createPlayList(const QString &fileName, bool useMetaData); MetaDataModel* createMetaDataModel(const QString &path, QObject *parent = 0); void showSettings(QWidget *parent); diff --git a/src/plugins/Input/mad/translations/mad_plugin_ru.ts b/src/plugins/Input/mad/translations/mad_plugin_ru.ts index 6f337c558..d471fea15 100644 --- a/src/plugins/Input/mad/translations/mad_plugin_ru.ts +++ b/src/plugins/Input/mad/translations/mad_plugin_ru.ts @@ -44,27 +44,27 @@ <message> <location filename="../mpegmetadatamodel.cpp" line="69"/> <source>Format</source> - <translation type="unfinished">Формат</translation> + <translation>Формат</translation> </message> <message> <location filename="../mpegmetadatamodel.cpp" line="71"/> <source>Bitrate</source> - <translation type="unfinished">Битовая частота</translation> + <translation>Битовая частота</translation> </message> <message> <location filename="../mpegmetadatamodel.cpp" line="71"/> <source>kbps</source> - <translation type="unfinished">Кб/с</translation> + <translation>Кб/с</translation> </message> <message> <location filename="../mpegmetadatamodel.cpp" line="73"/> <source>Samplerate</source> - <translation type="unfinished">Дискретизация</translation> + <translation>Дискретизация</translation> </message> <message> <location filename="../mpegmetadatamodel.cpp" line="73"/> <source>Hz</source> - <translation type="unfinished">Гц</translation> + <translation>Гц</translation> </message> <message> <location filename="../mpegmetadatamodel.cpp" line="77"/> @@ -72,49 +72,49 @@ <location filename="../mpegmetadatamodel.cpp" line="83"/> <location filename="../mpegmetadatamodel.cpp" line="86"/> <source>Mode</source> - <translation type="unfinished">Режим</translation> + <translation>Режим</translation> </message> <message> <location filename="../mpegmetadatamodel.cpp" line="89"/> <source>KB</source> - <translation type="unfinished">Кб</translation> + <translation>Кб</translation> </message> <message> <location filename="../mpegmetadatamodel.cpp" line="90"/> <source>File size</source> - <translation type="unfinished">Размер файла</translation> + <translation>Размер файла</translation> </message> <message> <location filename="../mpegmetadatamodel.cpp" line="92"/> <location filename="../mpegmetadatamodel.cpp" line="94"/> <source>Protection</source> - <translation type="unfinished">Защита</translation> + <translation>Защита</translation> </message> <message> <location filename="../mpegmetadatamodel.cpp" line="92"/> <location filename="../mpegmetadatamodel.cpp" line="96"/> <location filename="../mpegmetadatamodel.cpp" line="100"/> <source>Yes</source> - <translation type="unfinished">Есть</translation> + <translation>Да</translation> </message> <message> <location filename="../mpegmetadatamodel.cpp" line="94"/> <location filename="../mpegmetadatamodel.cpp" line="98"/> <location filename="../mpegmetadatamodel.cpp" line="102"/> <source>No</source> - <translation type="unfinished">Нет</translation> + <translation>Нет</translation> </message> <message> <location filename="../mpegmetadatamodel.cpp" line="96"/> <location filename="../mpegmetadatamodel.cpp" line="98"/> <source>Copyright</source> - <translation type="unfinished">Авторские права</translation> + <translation>Авторские права</translation> </message> <message> <location filename="../mpegmetadatamodel.cpp" line="100"/> <location filename="../mpegmetadatamodel.cpp" line="102"/> <source>Original</source> - <translation type="unfinished">Оригинальный</translation> + <translation>Оригинальный</translation> </message> </context> <context> diff --git a/src/qmmp/CMakeLists.txt b/src/qmmp/CMakeLists.txt index b3d6904af..e27326517 100644 --- a/src/qmmp/CMakeLists.txt +++ b/src/qmmp/CMakeLists.txt @@ -57,6 +57,7 @@ SET(libqmmp_SRCS qmmpaudioengine.cpp abstractengine.cpp audioparameters.cpp + inputsource.cpp ) SET(libqmmp_MOC_HDRS @@ -84,6 +85,7 @@ SET(libqmmp_MOC_HDRS qmmpaudioengine.h abstractengine.h audioparameters.h + inputsource.h ) SET(libqmmp_DEVEL_HDRS diff --git a/src/qmmp/abstractengine.h b/src/qmmp/abstractengine.h index 75829174f..442e02da7 100644 --- a/src/qmmp/abstractengine.h +++ b/src/qmmp/abstractengine.h @@ -27,6 +27,7 @@ #include <QThread> class QIODevice; +class InputSource; /*! * @author Ilya Kotov <forkotov02@hotmail.ru> @@ -42,7 +43,8 @@ public: * Prepares decoder for usage. * Subclass should reimplement this function. */ - virtual bool initialize(const QString &source, QIODevice *input = 0) = 0; + //virtual bool initialize(const QString &source, QIODevice *input = 0) = 0; + virtual bool enqueue(InputSource *source) = 0; /*! * Returns the total time in milliseconds. * Subclass should reimplement this function. diff --git a/src/qmmp/audioparameters.cpp b/src/qmmp/audioparameters.cpp index 0a858a1e4..34ffe98a9 100644 --- a/src/qmmp/audioparameters.cpp +++ b/src/qmmp/audioparameters.cpp @@ -35,7 +35,7 @@ bool AudioParameters::operator==(const AudioParameters &p) const bool AudioParameters::operator!=(const AudioParameters &p) const { - return !operator!=(p); + return !operator==(p); } quint32 AudioParameters::sampleRate() const diff --git a/src/qmmp/decoder.cpp b/src/qmmp/decoder.cpp index 73a8816c1..151a1a23a 100644 --- a/src/qmmp/decoder.cpp +++ b/src/qmmp/decoder.cpp @@ -31,11 +31,7 @@ Decoder::Decoder(QIODevice *input) : m_input(input) {} Decoder::~Decoder() -{ - if(m_input) - m_input->deleteLater(); - m_input = 0; -} +{} void Decoder::configure(quint32 srate, int chan, int bps) { diff --git a/src/qmmp/decoderfactory.h b/src/qmmp/decoderfactory.h index 144d3ccd7..f71c5e9af 100644 --- a/src/qmmp/decoderfactory.h +++ b/src/qmmp/decoderfactory.h @@ -84,10 +84,10 @@ public: virtual const DecoderProperties properties() const = 0; /*! * Creates decoder object. - * @param input Input data (if required) * @param path File path + * @param input Input data (if required) */ - virtual Decoder *create(QIODevice *input = 0, const QString &path = QString()) = 0; + virtual Decoder *create(const QString &path , QIODevice *input = 0) = 0; /*! * Extracts metadata and audio information from file \b path and returns a list of FileInfo items. * One file may contain several playlist items (for example: cda disk or flac with embedded cue) diff --git a/src/qmmp/inputsource.cpp b/src/qmmp/inputsource.cpp new file mode 100644 index 000000000..f69912b42 --- /dev/null +++ b/src/qmmp/inputsource.cpp @@ -0,0 +1,72 @@ +/*************************************************************************** + * Copyright (C) 2009 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 "streamreader.h" +#include "inputsource.h" + +InputSource::InputSource(const QString &source, QObject *parent) : QObject(parent) +{ + m_device = 0; + m_isValid = FALSE; + m_url = source; + QUrl url; + if (source.contains("://")) //url + url = source; + else if (QFile::exists(source)) + { + url = QUrl::fromLocalFile(source); + } + else + { + qDebug("InputSource: file doesn't exist"); + return; + } + m_url = url; + if (url.scheme() == "file") + { + m_device = new QFile(source, this); + /*if (!m_device->open(QIODevice::ReadOnly)) + { + qDebug("InputSource: cannot open input"); + return FALSE; + }*/ + } + if (url.scheme() == "http") + { + m_device = new StreamReader(source, this); + //connect(m_input, SIGNAL(bufferingProgress(int)), SIGNAL(bufferingProgress(int))); + connect(m_device, SIGNAL(readyRead()),SIGNAL(readyRead())); + qobject_cast<StreamReader *>(m_device)->downloadFile(); + return; + } + m_isValid = FALSE; +} + +const QUrl InputSource::url() +{ + return m_url; +} + +QIODevice *InputSource::ioDevice() +{ + return m_device; +} + diff --git a/src/qmmp/inputsource.h b/src/qmmp/inputsource.h new file mode 100644 index 000000000..d68ac91b7 --- /dev/null +++ b/src/qmmp/inputsource.h @@ -0,0 +1,46 @@ +/*************************************************************************** + * Copyright (C) 2009 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 INPUTSOURCE_H +#define INPUTSOURCE_H + +#include <QObject> +#include <QString> +#include <QUrl> +#include <QIODevice> + +class InputSource : public QObject +{ +Q_OBJECT +public: + InputSource(const QString &source, QObject *parent = 0); + QIODevice *ioDevice(); + const QUrl url(); + +signals: + void readyRead(); + +private: + QUrl m_url; + QIODevice *m_device; + bool m_isValid; +}; + +#endif // INPUTSOURCE_H diff --git a/src/qmmp/output.cpp b/src/qmmp/output.cpp index 87bce44c8..ca4b73805 100644 --- a/src/qmmp/output.cpp +++ b/src/qmmp/output.cpp @@ -33,7 +33,6 @@ Output::Output (QObject* parent) : QThread (parent), m_recycler (stackSize()) void Output::configure(quint32 freq, int chan, int prec) { - qDebug("%u -- %d -- %d", freq, chan, prec); m_frequency = freq; m_channels = chan; m_precision = prec; @@ -164,7 +163,7 @@ void Output::run() { mutex()->lock (); recycler()->mutex()->lock (); - done = m_userStop; + done = m_userStop || (m_finish && recycler()->empty()); while (!done && (recycler()->empty() || m_pause)) { @@ -172,7 +171,7 @@ void Output::run() recycler()->cond()->wakeOne(); recycler()->cond()->wait(recycler()->mutex()); mutex()->lock (); - done = m_userStop; + done = m_userStop || m_finish; } status(); if (!b) @@ -181,6 +180,7 @@ void Output::run() if (b && b->rate) m_kbps = b->rate; } + recycler()->cond()->wakeOne(); recycler()->mutex()->unlock(); mutex()->unlock(); diff --git a/src/qmmp/qmmp.pro b/src/qmmp/qmmp.pro index c254399c8..1cbfb1945 100644 --- a/src/qmmp/qmmp.pro +++ b/src/qmmp/qmmp.pro @@ -24,7 +24,8 @@ HEADERS += recycler.h \ tagmodel.h \ abstractengine.h \ qmmpaudioengine.h \ - audioparameters.h + audioparameters.h \ + inputsource.h SOURCES += recycler.cpp \ decoder.cpp \ output.cpp \ @@ -44,7 +45,8 @@ SOURCES += recycler.cpp \ tagmodel.cpp \ abstractengine.cpp \ qmmpaudioengine.cpp \ - audioparameters.cpp + audioparameters.cpp \ + inputsource.cpp FORMS += unix:TARGET = ../../lib/qmmp win32:TARGET = ../../../bin/qmmp diff --git a/src/qmmp/qmmpaudioengine.cpp b/src/qmmp/qmmpaudioengine.cpp index ae2efff89..5ebcee90d 100644 --- a/src/qmmp/qmmpaudioengine.cpp +++ b/src/qmmp/qmmpaudioengine.cpp @@ -27,8 +27,10 @@ #include "decoder.h" #include "output.h" #include "decoderfactory.h" +#include "inputsource.h" #include "qmmpaudioengine.h" + extern "C" { #include "equ/iir.h" @@ -47,12 +49,12 @@ QmmpAudioEngine::QmmpAudioEngine(QObject *parent) m_bks = Buffer::size(); m_decoder = 0; m_output = 0; - m_decoder2 = 0; reset(); } QmmpAudioEngine::~QmmpAudioEngine() { + stop(); reset(); if(m_output_buf) delete [] m_output_buf; @@ -70,68 +72,42 @@ void QmmpAudioEngine::reset() m_bitrate = 0; m_chan = 0; m_bps = 0; - m_source.clear(); } - -bool QmmpAudioEngine::initialize(const QString &source, QIODevice *input) +bool QmmpAudioEngine::enqueue(InputSource *source) { - if(m_decoder && isRunning() && m_output && m_output->isRunning()) - { - m_factory = Decoder::findByPath(source); - if(!m_factory) - m_factory = Decoder::findByURL(QUrl(source)); - m_decoder2 = m_factory->create(input, source); - if(!m_decoder2->initialize()) - return FALSE; + DecoderFactory *factory = Decoder::findByURL(source->url()); - if(m_decoder2->audioParameters() == m_decoder->audioParameters()) - { - qDebug("accepted!!"); - m_source = source; - return TRUE; - } - delete m_decoder2; - m_decoder2 = 0; - } - else - m_decoder2 = 0; - stop(); - m_source = source; - m_output = Output::create(this); - m_output->recycler()->clear(); - if (!m_output) + if(!factory && source->url().scheme() == "file") + factory = Decoder::findByPath(source->url().toLocalFile()); + if(!factory && source->ioDevice()) + factory = Decoder::findByContent(source->ioDevice()); + if(!factory) { - qWarning("SoundCore: unable to create output"); - StateHandler::instance()->dispatch(Qmmp::FatalError); + qWarning("QmmpAudioEngine: unsupported file format"); return FALSE; } - if (!m_output->initialize()) + if(factory->properties().noInput && source->ioDevice()) + source->ioDevice()->close(); + Decoder *decoder = 0; + if(source->url().scheme() == "file") + decoder = factory->create(source->url().toLocalFile(), source->ioDevice()); + else + decoder = factory->create(source->url().toString(), source->ioDevice()); + if(!decoder->initialize()) { - qWarning("SoundCore: unable to initialize output"); - delete m_output; - m_output = 0; - StateHandler::instance()->dispatch(Qmmp::FatalError); + qWarning("QmmpAudioEngine: invalid file format"); + delete decoder; return FALSE; } - - m_factory = Decoder::findByPath(source); - if(!m_factory) - m_factory = Decoder::findByURL(QUrl(source)); - m_decoder = m_factory->create(input, source); - if (!m_decoder) + if(!m_output) { - qWarning("SoundCore: unsupported fileformat"); - stop(); - StateHandler::instance()->dispatch(Qmmp::NormalError); - return FALSE; + m_output = createOutput(decoder); + if(!m_output) + return FALSE; } - if(!m_decoder->initialize()) - return FALSE; - - m_output->configure(m_decoder->audioParameters().sampleRate(), - m_decoder->audioParameters().channels(), - m_decoder->audioParameters().bits()); + m_decoders.enqueue(decoder); + m_inputs.insert(decoder, source); return TRUE; } @@ -143,11 +119,6 @@ qint64 QmmpAudioEngine::totalTime() return 0; } -Output *QmmpAudioEngine::output() -{ - return m_output; -} - void QmmpAudioEngine::setEQ(double bands[10], double preamp) { set_preamp(0, 1.0 + 0.0932471 *preamp + 0.00279033 * preamp * preamp); @@ -203,11 +174,6 @@ void QmmpAudioEngine::seek(qint64 time) } } -int QmmpAudioEngine::bitrate() -{ - return 0; -} - void QmmpAudioEngine::pause() { if (m_output) @@ -270,13 +236,14 @@ void QmmpAudioEngine::stop() m_output = 0; } - if(m_decoder) + while(!m_decoders.isEmpty()) { - qDebug("delete m_decoder"); - delete m_decoder; - m_decoder = 0; + Decoder *d = m_decoders.dequeue(); + delete m_inputs.take(d); + delete d; } reset(); + m_decoder = 0; } qint64 QmmpAudioEngine::produceSound(char *data, qint64 size, quint32 brate, int chan) @@ -312,7 +279,7 @@ qint64 QmmpAudioEngine::produceSound(char *data, qint64 size, quint32 brate, int prev_data = out_data; } - Buffer *b = output()->recycler()->get(w); + Buffer *b = m_output->recycler()->get(w); memcpy(b->data, out_data, w); @@ -325,7 +292,7 @@ qint64 QmmpAudioEngine::produceSound(char *data, qint64 size, quint32 brate, int b->nbytes = w; b->rate = brate; - output()->recycler()->add(); + m_output->recycler()->add(); size -= sz; memmove(data, data + sz, size); @@ -334,11 +301,11 @@ qint64 QmmpAudioEngine::produceSound(char *data, qint64 size, quint32 brate, int void QmmpAudioEngine::finish() { - if (output()) + if (m_output) { - output()->mutex()->lock (); - output()->finish(); - output()->mutex()->unlock(); + m_output->mutex()->lock (); + m_output->finish(); + m_output->mutex()->unlock(); } emit playbackFinished(); } @@ -348,9 +315,15 @@ void QmmpAudioEngine::run() Q_ASSERT(m_chan == 0); Q_ASSERT(!m_output_buf); mutex()->lock (); - if (m_output) - m_output->start(); qint64 len = 0; + if(m_decoders.isEmpty()) + { + mutex()->unlock (); + return; + } + + m_decoder = m_decoders.dequeue(); + m_output->start(); mutex()->unlock(); sendMetaData(); @@ -364,10 +337,10 @@ void QmmpAudioEngine::run() { m_decoder->seek(m_seekTime); m_seekTime = -1; - output()->recycler()->mutex()->lock (); - while(output()->recycler()->used() > 1) - output()->recycler()->done(); - output()->recycler()->mutex()->unlock (); + m_output->recycler()->mutex()->lock (); + while(m_output->recycler()->used() > 1) + m_output->recycler()->done(); + m_output->recycler()->mutex()->unlock (); } len = m_decoder->read((char *)(m_output_buf + m_output_at), @@ -377,39 +350,64 @@ void QmmpAudioEngine::run() { m_bitrate = m_decoder->bitrate(); m_output_at += len; - if (output()) + if (m_output) flush(); } else if (len == 0) { - if(m_decoder2) + if(!m_decoders.isEmpty()) { - qDebug("next decoder"); + delete m_inputs.take(m_decoder); delete m_decoder; - m_decoder = m_decoder2; - emit playbackFinished(); - StateHandler::instance()->dispatch(Qmmp::Stopped); //fake stop/start cycle - StateHandler::instance()->dispatch(Qmmp::Buffering); - StateHandler::instance()->dispatch(Qmmp::Playing); - m_output->seek(0); //reset counter - mutex()->unlock(); - sendMetaData(); - continue; + m_decoder = m_decoders.dequeue(); + //use current output if possible + if(m_decoder->audioParameters() == m_ap) + { + emit playbackFinished(); + StateHandler::instance()->dispatch(Qmmp::Stopped); //fake stop/start cycle + StateHandler::instance()->dispatch(Qmmp::Buffering); + StateHandler::instance()->dispatch(Qmmp::Playing); + m_output->seek(0); //reset counter + mutex()->unlock(); + sendMetaData(); + continue; + } + else + { + flush(TRUE); + finish(); + //wake up waiting threads + cond()->wakeAll(); + mutex()->unlock(); + m_output->recycler()->mutex()->lock (); + m_output->recycler()->cond()->wakeAll(); + m_output->recycler()->mutex()->unlock(); + + m_output->wait(); + delete m_output; + m_output = createOutput(m_decoder); + if(m_output) + { + m_output->start(); + sendMetaData(); + continue; + } + } } flush(TRUE); - if (output()) + if (m_output) { - output()->recycler()->mutex()->lock (); + m_output->recycler()->mutex()->lock (); // end of stream - while (!output()->recycler()->empty() && !m_user_stop) + while (!m_output->recycler()->empty() && !m_user_stop) { - output()->recycler()->cond()->wakeOne(); + m_output->recycler()->cond()->wakeOne(); mutex()->unlock(); - output()->recycler()->cond()->wait(output()->recycler()->mutex()); + m_output->recycler()->cond()->wait(m_output->recycler()->mutex()); mutex()->lock (); } - output()->recycler()->mutex()->unlock(); + m_output->recycler()->mutex()->unlock(); } m_done = TRUE; m_finish = !m_user_stop; @@ -418,6 +416,12 @@ void QmmpAudioEngine::run() m_finish = TRUE; mutex()->unlock(); } + if(m_decoder) + { + delete m_inputs.take(m_decoder); + delete m_decoder; + m_decoder = 0; + } mutex()->lock (); if (m_finish) @@ -431,19 +435,19 @@ void QmmpAudioEngine::flush(bool final) while ((!m_done && !m_finish) && m_output_at > min) { - output()->recycler()->mutex()->lock (); + m_output->recycler()->mutex()->lock (); if(m_seekTime >= 0) { - while(output()->recycler()->used() > 1) - output()->recycler()->done(); - output()->recycler()->mutex()->unlock (); + while(m_output->recycler()->used() > 1) + m_output->recycler()->done(); + m_output->recycler()->mutex()->unlock (); m_output_at = 0; break; } - while ((!m_done && !m_finish) && output()->recycler()->full()) + while ((!m_done && !m_finish) && m_output->recycler()->full()) { mutex()->unlock(); - output()->recycler()->cond()->wait(output()->recycler()->mutex()); + m_output->recycler()->cond()->wait(m_output->recycler()->mutex()); mutex()->lock (); m_done = m_user_stop; } @@ -455,20 +459,23 @@ void QmmpAudioEngine::flush(bool final) m_output_at -= produceSound((char*)m_output_buf, m_output_at, m_bitrate, m_chan); } - if (output()->recycler()->full()) + if (m_output->recycler()->full()) { - output()->recycler()->cond()->wakeOne(); + m_output->recycler()->cond()->wakeOne(); } - output()->recycler()->mutex()->unlock(); + m_output->recycler()->mutex()->unlock(); } } void QmmpAudioEngine::sendMetaData() { - if (QFile::exists(m_source)) //send metadata for local files + if(!m_decoder || m_inputs.isEmpty()) + return; + QUrl url = m_inputs.value(m_decoder)->url(); + if (url.scheme() == "file") //send metadata for local files only { - QList <FileInfo *> list = m_factory->createPlayList(m_source, TRUE); + QList <FileInfo *> list = Decoder::createPlayList(url.toLocalFile(), TRUE); if (!list.isEmpty()) { StateHandler::instance()->dispatch(list[0]->metaData()); @@ -477,3 +484,26 @@ void QmmpAudioEngine::sendMetaData() } } } + +Output *QmmpAudioEngine::createOutput(Decoder *d) +{ + m_ap = d->audioParameters(); + Output *output = Output::create(0); + if(!output) + { + qWarning("QmmpAudioEngine: unable to create output"); + StateHandler::instance()->dispatch(Qmmp::FatalError); + return 0; + } + if (!output->initialize()) + { + qWarning("SoundCore: unable to initialize output"); + delete output; + output = 0; + StateHandler::instance()->dispatch(Qmmp::FatalError); + return FALSE; + } + output->configure(m_ap.sampleRate(), m_ap.channels(), m_ap.bits()); + return output; +} + diff --git a/src/qmmp/qmmpaudioengine.h b/src/qmmp/qmmpaudioengine.h index 1cfed931b..e16ecef72 100644 --- a/src/qmmp/qmmpaudioengine.h +++ b/src/qmmp/qmmpaudioengine.h @@ -21,7 +21,10 @@ #ifndef QMMPAUDIOENGINE_H #define QMMPAUDIOENGINE_H +#include <QQueue> +#include <QHash> #include "abstractengine.h" +#include "audioparameters.h" class QIODevice; class Output; @@ -29,6 +32,7 @@ class Effect; class DecoderFactory; class StateHandler; class Decoder; +class InputSource; class QmmpAudioEngine : public AbstractEngine @@ -38,13 +42,11 @@ public: QmmpAudioEngine(QObject *parent); ~QmmpAudioEngine(); - bool initialize(const QString &source, QIODevice *input = 0); + bool enqueue(InputSource *source); qint64 totalTime(); void seek(qint64 time); void stop(); - int bitrate(); void pause(); - Output *output(); void setEQ(double bands[10], double preamp); void setEQEnabled(bool on); @@ -60,6 +62,7 @@ private: void flush(bool = FALSE); qint64 produceSound(char *data, qint64 size, quint32 brate, int chan); void sendMetaData(); + Output *createOutput(Decoder *d); DecoderFactory *m_factory; QList <Effect*> m_effects; @@ -75,8 +78,10 @@ private: int m_bitrate, m_chan, m_bps; unsigned char *m_output_buf; Decoder *m_decoder; - QString m_source; - Decoder *m_decoder2; + QQueue <Decoder*> m_decoders; + QHash <Decoder*, InputSource*> m_inputs; + AudioParameters m_ap; + }; #endif // QMMPAUDIOENGINE_H diff --git a/src/qmmp/soundcore.cpp b/src/qmmp/soundcore.cpp index 83d268a88..271711847 100644 --- a/src/qmmp/soundcore.cpp +++ b/src/qmmp/soundcore.cpp @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 2006-2008 by Ilya Kotov * + * Copyright (C) 2006-2009 by Ilya Kotov * * forkotov02@hotmail.ru * * * * This program is free software; you can redistribute it and/or modify * @@ -29,6 +29,7 @@ #include "streamreader.h" #include "effect.h" #include "statehandler.h" +#include "inputsource.h" #include "volumecontrol.h" #include "soundcore.h" @@ -73,67 +74,26 @@ SoundCore::~SoundCore() stop(); } -bool SoundCore::play(const QString &source, bool queue) +bool SoundCore::play(const QString &source, bool queue) { if(!queue) stop(); + m_source = source; - /*if (m_handler->state() != Qmmp::Stopped) //clear error state - m_handler->dispatch(Qmmp::Stopped); - m_handler->dispatch(Qmmp::Buffering); //buffering state*/ + m_inputSource = new InputSource(source, this); - QUrl url; - if (source.contains("://")) //url - url = source; - else if (QFile::exists(source)) - url = QUrl::fromLocalFile(source); + if(m_inputSource->ioDevice()) + connect(m_inputSource->ioDevice(), SIGNAL(readyRead()), SLOT(decode())); else - { - qDebug("SoundCore: file doesn't exist"); - m_handler->dispatch(Qmmp::NormalError); - return FALSE; - } - - m_factory = Decoder::findByURL(url); - m_input = 0; - if (m_factory) return decode(); - if (url.scheme() == "file") - { - if ((m_factory = Decoder::findByPath(m_source))) - { - m_input = new QFile(m_source); - if (!m_input->open(QIODevice::ReadOnly)) - { - qDebug("SoundCore: cannot open input"); - stop(); - m_handler->dispatch(Qmmp::NormalError); - return FALSE; - } - return decode(); - } - else - { - qWarning("SoundCore: unsupported fileformat"); - stop(); - m_handler->dispatch(Qmmp::NormalError); - return FALSE; - } - } - if (url.scheme() == "http") - { - m_input = new StreamReader(source, this); - connect(m_input, SIGNAL(bufferingProgress(int)), SIGNAL(bufferingProgress(int))); - connect(m_input, SIGNAL(readyRead()),SLOT(decode())); - qobject_cast<StreamReader *>(m_input)->downloadFile(); - return TRUE; - } - qWarning("SoundCore: unsupported fileformat"); - stop(); - m_handler->dispatch(Qmmp::NormalError); - return FALSE; + if(qobject_cast<StreamReader *>(m_inputSource->ioDevice())) + qobject_cast<StreamReader *>(m_inputSource->ioDevice())->downloadFile(); + else + m_inputSource->ioDevice()->open(QIODevice::ReadOnly); + return decode(); + return TRUE; } void SoundCore::stop() @@ -271,21 +231,8 @@ QString SoundCore::metaData(Qmmp::MetaData key) bool SoundCore::decode() { - if (!m_factory) - { - if (!m_input->open(QIODevice::ReadOnly)) - { - qDebug("SoundCore:: cannot open input"); - m_handler->dispatch(Qmmp::NormalError); - return FALSE; - } - if (!(m_factory = Decoder::findByMime(qobject_cast<StreamReader *>(m_input)->contentType()))) - if (!(m_factory = Decoder::findByContent(m_input))) - { - m_handler->dispatch(Qmmp::NormalError); - return FALSE; - } - } + qDebug("ready"); + disconnect(m_inputSource->ioDevice(), SIGNAL(readyRead()), this, SLOT(decode())); if(!m_engine) { @@ -293,10 +240,16 @@ bool SoundCore::decode() connect(m_engine, SIGNAL(playbackFinished()), SIGNAL(finished())); } - if(m_engine->initialize(m_source, m_input)) + if(m_engine->enqueue(m_inputSource)) + { + m_inputSource->setParent(m_engine); m_engine->start(); + } else + { + delete m_inputSource; return FALSE; + } setEQ(m_bands, m_preamp); setEQEnabled(m_useEQ); diff --git a/src/qmmp/soundcore.h b/src/qmmp/soundcore.h index b8d103ba9..f35d96656 100644 --- a/src/qmmp/soundcore.h +++ b/src/qmmp/soundcore.h @@ -30,6 +30,7 @@ class QIODevice; class VolumeControl; class QmmpAudioEngine; +class InputSource; /*! \brief The SoundCore class provides a simple interface for audio playback. * @author Ilya Kotov <forkotov02@hotmail.ru> @@ -225,6 +226,7 @@ private: StateHandler *m_handler; VolumeControl *m_volumeControl; QmmpAudioEngine *m_engine; + InputSource *m_inputSource; }; #endif diff --git a/src/qmmpui/mediaplayer.cpp b/src/qmmpui/mediaplayer.cpp index d0f55ba9e..43038724e 100644 --- a/src/qmmpui/mediaplayer.cpp +++ b/src/qmmpui/mediaplayer.cpp @@ -65,7 +65,6 @@ void MediaPlayer::initialize(SoundCore *core, PlayListModel *model) m_repeat = FALSE; connect(m_core, SIGNAL(aboutToFinish()), SLOT(updateNextUrl())); connect(m_core, SIGNAL(finished()), SLOT(next())); - //connect(m_model, SIGNAL(listChanged()), SLOT(updateNextUrl())); } PlayListModel *MediaPlayer::playListModel() @@ -80,7 +79,6 @@ bool MediaPlayer::isRepeatable() const void MediaPlayer::play() { - //disconnect(m_model, SIGNAL(listChanged()), this, SLOT(updateNextUrl())); m_model->doCurrentVisibleRequest(); if (m_core->state() == Qmmp::Paused) { @@ -139,11 +137,7 @@ void MediaPlayer::play() } } else - { m_skips = 0; - /*updateNextUrl(); - connect(m_model, SIGNAL(listChanged()), this, SLOT(updateNextUrl()));*/ - } } void MediaPlayer::stop() @@ -154,7 +148,6 @@ void MediaPlayer::stop() void MediaPlayer::next() { - //disconnect(m_model, SIGNAL(listChanged()), this, SLOT(updateNextUrl())); if (!m_model->isEmptyQueue()) { m_model->setCurrentToQueued(); @@ -175,7 +168,6 @@ void MediaPlayer::next() void MediaPlayer::previous() { - //disconnect(m_model, SIGNAL(listChanged()), this, SLOT(updateNextUrl())); if (!m_model->previous()) { stop(); @@ -204,7 +196,6 @@ void MediaPlayer::setRepeatable(bool r) } m_repeat = r; emit repeatableChanged(r); - //updateNextUrl(); } void MediaPlayer::updateNextUrl() diff --git a/src/qmmpui/translations/libqmmpui_ru.ts b/src/qmmpui/translations/libqmmpui_ru.ts index f43c9650e..c3040c409 100644 --- a/src/qmmpui/translations/libqmmpui_ru.ts +++ b/src/qmmpui/translations/libqmmpui_ru.ts @@ -6,47 +6,47 @@ <message> <location filename="../detailsdialog.cpp" line="74"/> <source>Title</source> - <translation type="unfinished"></translation> + <translation>Название</translation> </message> <message> <location filename="../detailsdialog.cpp" line="75"/> <source>Artist</source> - <translation type="unfinished"></translation> + <translation>Исполнитель</translation> </message> <message> <location filename="../detailsdialog.cpp" line="76"/> <source>Album</source> - <translation type="unfinished"></translation> + <translation>Альбом</translation> </message> <message> <location filename="../detailsdialog.cpp" line="77"/> <source>Comment</source> - <translation type="unfinished"></translation> + <translation>Комментарий</translation> </message> <message> <location filename="../detailsdialog.cpp" line="78"/> <source>Genre</source> - <translation type="unfinished"></translation> + <translation>Жанр</translation> </message> <message> <location filename="../detailsdialog.cpp" line="79"/> <source>Composer</source> - <translation type="unfinished"></translation> + <translation>Композитр</translation> </message> <message> <location filename="../detailsdialog.cpp" line="81"/> <source>Year</source> - <translation type="unfinished"></translation> + <translation>Год</translation> </message> <message> <location filename="../detailsdialog.cpp" line="83"/> <source>Track</source> - <translation type="unfinished"></translation> + <translation>Дорожка</translation> </message> <message> <location filename="../detailsdialog.cpp" line="85"/> <source>Disc number</source> - <translation type="unfinished"></translation> + <translation>Номер диска</translation> </message> <message> <location filename="../detailsdialog.ui" line="14"/> @@ -129,54 +129,54 @@ p, li { white-space: pre-wrap; } <message> <location filename="../tageditor.ui" line="38"/> <source>Title:</source> - <translation type="unfinished">Название:</translation> + <translation>Название:</translation> </message> <message> <location filename="../tageditor.ui" line="64"/> <source>Artist:</source> - <translation type="unfinished">Исполнитель:</translation> + <translation>Исполнитель:</translation> </message> <message> <location filename="../tageditor.ui" line="90"/> <source>Album:</source> - <translation type="unfinished">Альбом:</translation> + <translation>Альбом:</translation> </message> <message> <location filename="../tageditor.ui" line="113"/> <source>Composer:</source> - <translation type="unfinished">Композитор:</translation> + <translation>Композитор:</translation> </message> <message> <location filename="../tageditor.ui" line="133"/> <source>Genre:</source> - <translation type="unfinished">Жанр:</translation> + <translation>Жанр:</translation> </message> <message> <location filename="../tageditor.ui" line="159"/> <source>Disc number:</source> - <translation type="unfinished">Номер диска:</translation> + <translation>Номер диска:</translation> </message> <message> <location filename="../tageditor.ui" line="169"/> <location filename="../tageditor.ui" line="201"/> <location filename="../tageditor.ui" line="239"/> <source>?</source> - <translation type="unfinished"></translation> + <translation></translation> </message> <message> <location filename="../tageditor.ui" line="182"/> <source>Track:</source> - <translation type="unfinished"></translation> + <translation></translation> </message> <message> <location filename="../tageditor.ui" line="220"/> <source>Year:</source> - <translation type="unfinished"></translation> + <translation></translation> </message> <message> <location filename="../tageditor.ui" line="252"/> <source>Comment:</source> - <translation type="unfinished">Комментарий:</translation> + <translation>Комментарий:</translation> </message> <message> <location filename="../tageditor.ui" line="274"/> |
