diff options
| author | trialuser02 <trialuser02@90c681e8-e032-0410-971d-27865f9a5e38> | 2008-09-21 11:25:50 +0000 |
|---|---|---|
| committer | trialuser02 <trialuser02@90c681e8-e032-0410-971d-27865f9a5e38> | 2008-09-21 11:25:50 +0000 |
| commit | 1d58bc219b471db64390a20f361921842efbf602 (patch) | |
| tree | 9359e53dd4d52f8b364ef8305ca2249d5abfa43f | |
| parent | e7ea59067e6c975a16926647376175f0f2ab2afa (diff) | |
| download | qmmp-1d58bc219b471db64390a20f361921842efbf602.tar.gz qmmp-1d58bc219b471db64390a20f361921842efbf602.tar.bz2 qmmp-1d58bc219b471db64390a20f361921842efbf602.zip | |
enabled stream support
git-svn-id: http://svn.code.sf.net/p/qmmp-dev/code/trunk/qmmp@553 90c681e8-e032-0410-971d-27865f9a5e38
| -rw-r--r-- | src/plugins/Input/mad/decoder_mad.cpp | 2 | ||||
| -rw-r--r-- | src/plugins/Input/mad/decodermadfactory.cpp | 2 | ||||
| -rw-r--r-- | src/plugins/Input/mad/decodermadfactory.h | 2 | ||||
| -rw-r--r-- | src/qmmp/decoder.cpp | 211 | ||||
| -rw-r--r-- | src/qmmp/decoder.h | 13 | ||||
| -rw-r--r-- | src/qmmp/decoderfactory.h | 19 | ||||
| -rw-r--r-- | src/qmmp/soundcore.cpp | 95 | ||||
| -rw-r--r-- | src/qmmp/soundcore.h | 4 | ||||
| -rw-r--r-- | src/qmmp/statehandler.cpp | 22 | ||||
| -rw-r--r-- | src/ui/aboutdialog.cpp | 2 | ||||
| -rw-r--r-- | src/ui/configdialog.cpp | 6 | ||||
| -rw-r--r-- | src/ui/mainwindow.cpp | 2 | ||||
| -rw-r--r-- | src/ui/pluginitem.cpp | 1 |
13 files changed, 226 insertions, 155 deletions
diff --git a/src/plugins/Input/mad/decoder_mad.cpp b/src/plugins/Input/mad/decoder_mad.cpp index 941dcee8b..2cd8567a0 100644 --- a/src/plugins/Input/mad/decoder_mad.cpp +++ b/src/plugins/Input/mad/decoder_mad.cpp @@ -316,7 +316,7 @@ bool DecoderMAD::findHeader() if (!result) return FALSE; - if (!is_vbr) + if (!is_vbr && !input()->isSequential()) { double time = (input()->size() * 8.0) / (header.bitrate); double timefrac = (double)time - ((long)(time)); diff --git a/src/plugins/Input/mad/decodermadfactory.cpp b/src/plugins/Input/mad/decodermadfactory.cpp index 57d299f40..10afdefc4 100644 --- a/src/plugins/Input/mad/decodermadfactory.cpp +++ b/src/plugins/Input/mad/decodermadfactory.cpp @@ -93,7 +93,7 @@ const DecoderProperties DecoderMADFactory::properties() const return properties; } -Decoder *DecoderMADFactory::create(QObject *parent, QIODevice *input, Output *output) +Decoder *DecoderMADFactory::create(QObject *parent, QIODevice *input, Output *output, const QString &) { return new DecoderMAD(parent, this, input, output); } diff --git a/src/plugins/Input/mad/decodermadfactory.h b/src/plugins/Input/mad/decodermadfactory.h index 5688adbe9..3b1a45818 100644 --- a/src/plugins/Input/mad/decodermadfactory.h +++ b/src/plugins/Input/mad/decodermadfactory.h @@ -42,7 +42,7 @@ public: bool supports(const QString &source) const; bool canDecode(QIODevice *input) const; const DecoderProperties properties() const; - Decoder *create(QObject *, QIODevice *, Output *); + Decoder *create(QObject *, QIODevice *, Output *, const QString &); FileTag *createTag(const QString &source); QObject* showDetails(QWidget *parent, const QString &path); void showSettings(QWidget *parent); diff --git a/src/qmmp/decoder.cpp b/src/qmmp/decoder.cpp index 3d460e1ba..e5f7681d5 100644 --- a/src/qmmp/decoder.cpp +++ b/src/qmmp/decoder.cpp @@ -118,6 +118,99 @@ void Decoder::volume(int *l, int *r) m_mutex.unlock(); } +void Decoder::configure(quint32 srate, int chan, int bps) +{ + Effect* effect = 0; + foreach(effect, m_effects) + { + effect->configure(srate, chan, bps); + srate = effect->sampleRate(); + chan = effect->channels(); + bps = effect->bitsPerSample(); + } + if (m_output) + m_output->configure(srate, chan, bps); +} + +qint64 Decoder::produceSound(char *data, qint64 size, quint32 brate, int chan) +{ + ulong sz = size < blksize ? size : blksize; + + if (m_useEQ) + { + if (!m_eqInited) + { + init_iir(); + m_eqInited = TRUE; + } + iir((void*) data, sz, chan); + } + if (m_useVolume) + { + changeVolume(data, sz, chan); + } + char *out_data = data; + char *prev_data = data; + qint64 w = sz; + Effect* effect = 0; + foreach(effect, m_effects) + { + w = effect->process(prev_data, sz, &out_data); + + if (w <= 0) + { + // copy data if plugin can not process it + w = sz; + out_data = new char[w]; + memcpy(out_data, prev_data, w); + } + if (data != prev_data) + delete prev_data; + prev_data = out_data; + } + + Buffer *b = output()->recycler()->get(w); + + memcpy(b->data, out_data, w); + + if (data != out_data) + delete out_data; + + if (w < blksize + b->exceeding) + memset(b->data + w, 0, blksize + b->exceeding - w); + + b->nbytes = w;// blksize; + b->rate = brate; + + output()->recycler()->add(); + + size -= sz; + memmove(data, data + sz, size); + return sz; +} + +void Decoder::finish() +{ + //output()->wait(); + emit finished(); +} + +void Decoder::changeVolume(char *data, qint64 size, int chan) +{ + if (chan > 1) + for (qint64 i = 0; i < size/2; i+=2) + { + ((short*)data)[i]*= m_volLF/256.0; + ((short*)data)[i+1]*= m_volRF/256.0; + } + else + { + int l = qMax(m_volLF,m_volRF); + for (qint64 i = 0; i < size/2; i++) + ((short*)data)[i]*= l/256.0; + } +} + // static methods QList<DecoderFactory*> *Decoder::m_factories = 0; QStringList Decoder::m_files; @@ -185,7 +278,7 @@ QStringList Decoder::all() return l; } -QStringList Decoder::decoderFiles() +QStringList Decoder::files() { checkFactories(); return m_files; @@ -207,7 +300,7 @@ bool Decoder::supports(const QString &source) return FALSE; } -Decoder *Decoder::create(QObject *parent, const QString &source, +/*Decoder *Decoder::create(QObject *parent, const QString &source, QIODevice *input, Output *output) { @@ -236,7 +329,7 @@ Decoder *Decoder::create(QObject *parent, const QString &source, else output->setStateHandler(decoder->stateHandler()); return decoder; -} +}*/ DecoderFactory *Decoder::findByPath(const QString& source) { @@ -276,8 +369,7 @@ DecoderFactory *Decoder::findByMime(const QString& type) DecoderFactory *Decoder::findByContent(QIODevice *input) { checkFactories(); - DecoderFactory *fact; - foreach(fact, *m_factories) + foreach(DecoderFactory *fact, *m_factories) { if (fact->canDecode(input) && isEnabled(fact)) { @@ -288,6 +380,21 @@ DecoderFactory *Decoder::findByContent(QIODevice *input) return 0; } +DecoderFactory *Decoder::findByURL(const QUrl &url) +{ + checkFactories(); + foreach(DecoderFactory *fact, *m_factories) + { + if (fact->supports(url.path()) && isEnabled(fact) && + fact->properties().protocols.split(" ").contains(url.scheme())) + { + return fact; + } + } + qDebug("Decoder: unable to find factory by url"); + return 0; +} + void Decoder::setEnabled(DecoderFactory* factory, bool enable) { checkFactories(); @@ -350,101 +457,9 @@ QStringList Decoder::nameFilters() return filters; } -QList<DecoderFactory*> *Decoder::decoderFactories() +QList<DecoderFactory*> *Decoder::factories() { checkFactories(); return m_factories; } -void Decoder::configure(quint32 srate, int chan, int bps) -{ - Effect* effect = 0; - foreach(effect, m_effects) - { - effect->configure(srate, chan, bps); - srate = effect->sampleRate(); - chan = effect->channels(); - bps = effect->bitsPerSample(); - } - if (m_output) - m_output->configure(srate, chan, bps); -} - -qint64 Decoder::produceSound(char *data, qint64 size, quint32 brate, int chan) -{ - ulong sz = size < blksize ? size : blksize; - - if (m_useEQ) - { - if (!m_eqInited) - { - init_iir(); - m_eqInited = TRUE; - } - iir((void*) data,size,chan); - } - if (m_useVolume) - { - changeVolume(data, sz, chan); - } - char *out_data = data; - char *prev_data = data; - qint64 w = sz; - Effect* effect = 0; - foreach(effect, m_effects) - { - w = effect->process(prev_data, sz, &out_data); - - if (w <= 0) - { - // copy data if plugin can not procees it - w = sz; - out_data = new char[w]; - memcpy(out_data, prev_data, w); - } - if (data != prev_data) - delete prev_data; - prev_data = out_data; - } - - Buffer *b = output()->recycler()->get(w); - - memcpy(b->data, out_data, w); - - if (data != out_data) - delete out_data; - - if (w < blksize + b->exceeding) - memset(b->data + w, 0, blksize + b->exceeding - w); - - b->nbytes = w;// blksize; - b->rate = brate; - - output()->recycler()->add(); - - size -= sz; - memmove(data, data + sz, size); - return sz; -} - -void Decoder::finish() -{ - //output()->wait(); - emit finished(); -} - -void Decoder::changeVolume(char *data, qint64 size, int chan) -{ - if (chan > 1) - for (qint64 i = 0; i < size/2; i+=2) - { - ((short*)data)[i]*= m_volLF/256.0; - ((short*)data)[i+1]*= m_volRF/256.0; - } - else - { - int l = qMax(m_volLF,m_volRF); - for (qint64 i = 0; i < size/2; i++) - ((short*)data)[i]*= l/256.0; - } -} diff --git a/src/qmmp/decoder.h b/src/qmmp/decoder.h index d1f3818df..c74446916 100644 --- a/src/qmmp/decoder.h +++ b/src/qmmp/decoder.h @@ -13,6 +13,7 @@ #include <QWaitCondition> #include <QObject> #include <QStringList> +#include <QUrl> #include "filetag.h" @@ -33,8 +34,8 @@ class Decoder : public QThread { Q_OBJECT public: - Decoder(QObject *parent, DecoderFactory *d, - QIODevice *i, Output *o); + Decoder(QObject *parent, DecoderFactory *d, QIODevice *input = 0, Output *output = 0); + virtual ~Decoder(); // Standard Decoder API @@ -61,21 +62,21 @@ public: // static methods static QStringList all(); static bool supports(const QString &); - static Decoder *create(QObject *, const QString &, QIODevice *, Output *); + //static Decoder *create(QObject *, const QString &, QIODevice *, Output *); static DecoderFactory *findByPath(const QString&); static DecoderFactory *findByMime(const QString&); static DecoderFactory *findByContent(QIODevice *); + static DecoderFactory *findByURL(const QUrl &url); static FileTag *createTag(const QString&); static QStringList filters(); static QStringList nameFilters(); - static QList<DecoderFactory*> *decoderFactories(); - static QStringList decoderFiles(); + static QList<DecoderFactory*> *factories(); + static QStringList files(); static void setEnabled(DecoderFactory* factory, bool enable = TRUE); static bool isEnabled(DecoderFactory* factory); signals: void finished(); - //void stateChanged(const DecoderState&); protected: void configure(quint32 srate, int chan, int bps); diff --git a/src/qmmp/decoderfactory.h b/src/qmmp/decoderfactory.h index d67d1b564..954f597b2 100644 --- a/src/qmmp/decoderfactory.h +++ b/src/qmmp/decoderfactory.h @@ -32,16 +32,26 @@ class Decoder; class Output; class FileTag; -struct DecoderProperties +class DecoderProperties { +public: + DecoderProperties() + { + hasAbout = FALSE; + hasSettings = FALSE; + noInput = FALSE; + noOutput = FALSE; + + } QString name; QString filter; QString description; QString contentType; + QString protocols; bool hasAbout; bool hasSettings; - //bool streamSupport; - //bool needInput; + bool noInput; + bool noOutput; }; class DecoderFactory @@ -51,7 +61,8 @@ public: virtual bool supports(const QString &source) const = 0; virtual bool canDecode(QIODevice *) const = 0; virtual const DecoderProperties properties() const = 0; - virtual Decoder *create(QObject *, QIODevice *, Output *) = 0; + virtual Decoder *create(QObject *, QIODevice *input = 0, + Output *output = 0, const QString &path = QString()) = 0; virtual FileTag *createTag(const QString &source) = 0; virtual QObject* showDetails(QWidget *parent, const QString &path) = 0; virtual void showSettings(QWidget *parent) = 0; diff --git a/src/qmmp/soundcore.cpp b/src/qmmp/soundcore.cpp index be7c124d9..d390269e7 100644 --- a/src/qmmp/soundcore.cpp +++ b/src/qmmp/soundcore.cpp @@ -49,6 +49,7 @@ SoundCore::SoundCore(QObject *parent) m_preamp = 0; m_vis = 0; m_parentWidget = 0; + m_factory = 0; m_state = Qmmp::Stopped; for (int i = 1; i < 10; ++i) m_bands[i] = 0; @@ -65,27 +66,57 @@ bool SoundCore::play(const QString &source) stop(); if (m_state != Qmmp::Stopped) //clear error state setState(Qmmp::Stopped); - m_input = new QFile(source); - m_output = Output::create(this); - if (!m_output) + + if (QFile::exists(source)) //local file + m_url = QUrl::fromLocalFile(source); + else + m_url = source; + + m_factory = Decoder::findByURL(m_url); + if (m_factory) + return decode(); + + if (m_url.scheme() == "file") { - qWarning("SoundCore: unable to create output"); - setState(Qmmp::FatalError); - return FALSE; + if ((m_factory = Decoder::findByPath(m_url.path()))) + { + m_input = new QFile(m_url.path()); + if (!m_input->open(QIODevice::ReadOnly)) + { + qDebug("SoundCore: cannot open input"); + stop(); + setState(Qmmp::NormalError); + } + return decode(); + } + else + { + qWarning("SoundCore: unsupported fileformat"); + stop(); + setState(Qmmp::NormalError); + return FALSE; + } } - if (!m_output->initialize()) + if (m_url.scheme() == "http") { - qWarning("SoundCore: unable to initialize output"); - setState(Qmmp::FatalError); - return FALSE; + m_input = new StreamReader(source, this); + connect(m_input, SIGNAL(bufferingProgress(int)), SIGNAL(bufferingProgress(int))); + connect(m_input, SIGNAL(titleChanged(const QString&)), + SIGNAL(titleChanged(const QString&))); + connect(m_input, SIGNAL(readyRead()),SLOT(decode())); + qobject_cast<StreamReader *>(m_input)->downloadFile(); + return TRUE; } - m_source = source; - return decode(); - + qWarning("SoundCore: unsupported fileformat"); + stop(); + setState(Qmmp::NormalError); + return FALSE; } void SoundCore::stop() { + m_factory = 0; + m_url.clear(); if (m_decoder && m_decoder->isRunning()) { m_decoder->mutex()->lock (); @@ -292,9 +323,39 @@ void SoundCore::setState(Qmmp::State state) bool SoundCore::decode() { - if (!m_input || !m_output) - return FALSE; - m_decoder = Decoder::create(this, m_source, m_input, m_output); + if (!m_factory) + { + if (!m_input->open(QIODevice::ReadOnly)) + { + qDebug("SoundCore:: cannot open input"); + setState(Qmmp::NormalError); + return FALSE; + } + if (!(m_factory = Decoder::findByContent(m_input))) + { + setState(Qmmp::NormalError); + return FALSE; + } + } + if (!m_factory->properties().noOutput) + { + m_output = Output::create(this); + if (!m_output) + { + qWarning("SoundCore: unable to create output"); + setState(Qmmp::FatalError); + return FALSE; + } + if (!m_output->initialize()) + { + qWarning("SoundCore: unable to initialize output"); + delete m_output; + m_output = 0; + setState(Qmmp::FatalError); + return FALSE; + } + } + m_decoder = m_factory->create(this, m_input, m_output, m_url.path()); if (!m_decoder) { qWarning("SoundCore: unsupported fileformat"); @@ -313,6 +374,8 @@ bool SoundCore::decode() connect(handler, SIGNAL(metaDataChanged ()), SIGNAL(metaDataChanged ())); connect(handler, SIGNAL(stateChanged (Qmmp::State)), SLOT(setState(Qmmp::State))); connect(m_decoder, SIGNAL(finished()), SIGNAL(finished())); + if (m_output) + m_output->setStateHandler(handler); if (m_decoder->initialize()) { diff --git a/src/qmmp/soundcore.h b/src/qmmp/soundcore.h index 604ae8c65..a83a4f75a 100644 --- a/src/qmmp/soundcore.h +++ b/src/qmmp/soundcore.h @@ -1,6 +1,6 @@ /*************************************************************************** * Copyright (C) 2006-2008 by Ilya Kotov * - * forkotov02\hotmail.ru * + * 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 * @@ -156,6 +156,8 @@ private slots: private: Decoder* m_decoder; + DecoderFactory* m_factory; + QUrl m_url; Output* m_output; QIODevice* m_input; uint m_error; diff --git a/src/qmmp/statehandler.cpp b/src/qmmp/statehandler.cpp index 1bb1fb235..58fa9dea5 100644 --- a/src/qmmp/statehandler.cpp +++ b/src/qmmp/statehandler.cpp @@ -27,7 +27,6 @@ StateHandler::StateHandler(QObject *parent) { m_instance = this; m_elapsed = -1; - m_totalTime = 0; m_bitrate = 0; m_frequency = 0; m_precision = 0; @@ -55,11 +54,6 @@ void StateHandler::dispatch(qint64 elapsed, m_elapsed = elapsed; emit (elapsedChanged(elapsed)); } - /*if (m_totalTime != totalTime) - { - m_totalTime = totalTime; - emit (totalTimeChanged(totalTime)); - }*/ if (m_bitrate != bitrate) { m_bitrate = bitrate; @@ -105,27 +99,11 @@ void StateHandler::dispatch(const Qmmp::State &state) m_mutex.unlock(); } -/*void StateHandler::dispatchTotalTime(qint64 totalTime) -{ - m_mutex.lock(); - if (m_totalTime != totalTime) - { - m_totalTime = totalTime; - emit (totalTimeChanged(totalTime)); - } - m_mutex.unlock(); -}*/ - qint64 StateHandler::elapsed() { return m_elapsed; } -qint64 StateHandler::totalTime() -{ - return m_totalTime; -} - int StateHandler::bitrate() { return m_bitrate; diff --git a/src/ui/aboutdialog.cpp b/src/ui/aboutdialog.cpp index 128f89bc0..87f0317b0 100644 --- a/src/ui/aboutdialog.cpp +++ b/src/ui/aboutdialog.cpp @@ -82,7 +82,7 @@ QString AboutDialog::loadAbout() text.append("<p>"+getstringFromResource(tr(":txt/description_en.txt"))+"</p>"); text.append("<h5>"+tr("Input plugins:")+"</h5>"); text.append("<ul type=\"square\">"); - foreach(DecoderFactory *fact, *Decoder::decoderFactories()) + foreach(DecoderFactory *fact, *Decoder::factories()) { text.append("<li>"); text.append(fact->properties().name); diff --git a/src/ui/configdialog.cpp b/src/ui/configdialog.cpp index a27a8cb31..6b950d546 100644 --- a/src/ui/configdialog.cpp +++ b/src/ui/configdialog.cpp @@ -198,8 +198,8 @@ void ConfigDialog::loadPluginsInfo() load input plugins information */ QList <DecoderFactory *> *decoders = 0; - decoders = Decoder::decoderFactories(); - QStringList files = Decoder::decoderFiles(); + decoders = Decoder::factories(); + QStringList files = Decoder::files(); ui.inputPluginTable->setColumnCount ( 3 ); ui.inputPluginTable->verticalHeader()->hide(); ui.inputPluginTable->setHorizontalHeaderLabels ( QStringList() @@ -413,7 +413,7 @@ void ConfigDialog::showPluginSettings() case 0: { QList <DecoderFactory *> *decoders = 0; - decoders = Decoder::decoderFactories(); + decoders = Decoder::factories(); int row = ui.inputPluginTable->currentRow (); if ( !decoders || row<0 ) return; diff --git a/src/ui/mainwindow.cpp b/src/ui/mainwindow.cpp index fdf2e1bd7..e456183ed 100644 --- a/src/ui/mainwindow.cpp +++ b/src/ui/mainwindow.cpp @@ -202,7 +202,7 @@ void MainWindow::play() if (m_core->play(s)) { //display->setTime(0); - qDebug("play"); + //qDebug("play"); m_generalHandler->setTime(0); //display->setDuration(m_core->totalTime()); } diff --git a/src/ui/pluginitem.cpp b/src/ui/pluginitem.cpp index bbfdab306..1d5b7a3d8 100644 --- a/src/ui/pluginitem.cpp +++ b/src/ui/pluginitem.cpp @@ -156,3 +156,4 @@ GeneralFactory *GeneralPluginItem::factory() { return m_factory; } + |
