diff options
| -rw-r--r-- | src/plugins/Effect/crossfade/crossfadeplugin.cpp | 2 | ||||
| -rw-r--r-- | src/qmmp/soundcore.cpp | 167 | ||||
| -rw-r--r-- | src/qmmp/soundcore.h | 27 | ||||
| -rw-r--r-- | src/qmmp/statehandler.cpp | 23 | ||||
| -rw-r--r-- | src/qmmp/statehandler.h | 21 |
5 files changed, 92 insertions, 148 deletions
diff --git a/src/plugins/Effect/crossfade/crossfadeplugin.cpp b/src/plugins/Effect/crossfade/crossfadeplugin.cpp index 8da9ee46f..eee8612ee 100644 --- a/src/plugins/Effect/crossfade/crossfadeplugin.cpp +++ b/src/plugins/Effect/crossfade/crossfadeplugin.cpp @@ -56,7 +56,7 @@ void CrossfadePlugin::applyEffect(Buffer *b) return; case CHECKING: //next source has been received and current engine will be used to play it - if(m_handler->nextEngine() == m_handler->currentEngine()) + if(SoundCore::instance()->nextTrackAccepted()) m_state = PREPARING; else return; diff --git a/src/qmmp/soundcore.cpp b/src/qmmp/soundcore.cpp index 156bc504c..8b528f916 100644 --- a/src/qmmp/soundcore.cpp +++ b/src/qmmp/soundcore.cpp @@ -44,11 +44,10 @@ SoundCore::SoundCore(QObject *parent) qFatal("SoundCore: only one instance is allowed"); m_instance = this; m_decoder = 0; - m_error = false; m_parentWidget = 0; m_engine = 0; - m_pendingEngine = 0; m_volumeControl = 0; + m_nextState = NO_ENGINE; m_handler = new StateHandler(this); connect(m_handler, SIGNAL(elapsedChanged(qint64)), SIGNAL(elapsedChanged(qint64))); connect(m_handler, SIGNAL(bitrateChanged(int)), SIGNAL(bitrateChanged(int))); @@ -72,48 +71,43 @@ bool SoundCore::play(const QString &source, bool queue, qint64 offset) { if(!queue) stop(); - else - { - qDeleteAll(m_pendingSources); - m_pendingSources.clear(); - if(m_pendingEngine) - delete m_pendingEngine; - m_pendingEngine = 0; - } + MetaDataManager::instance(); //create metadata manager InputSource *s = InputSource::create(source, this); s->setOffset(offset); - m_pendingSources.append(s); - if(state() == Qmmp::Stopped) - m_handler->dispatch(Qmmp::Buffering); - connect(s, SIGNAL(ready()), SLOT(enqueue())); - connect(s, SIGNAL(error()), SLOT(enqueue())); - bool ok = s->initialize(); - if(!ok) + m_sources.enqueue(s); + + connect(s, SIGNAL(ready()), SLOT(startNextSource())); + connect(s, SIGNAL(error()), SLOT(startNextSource())); + + if(!s->initialize()) { - m_pendingSources.removeAll(s); + m_sources.removeAll(s); s->deleteLater(); if(m_handler->state() == Qmmp::Stopped || m_handler->state() == Qmmp::Buffering) - m_handler->dispatch(Qmmp::NormalError); + m_handler->dispatch(Qmmp::NormalError); + return false; } - return ok; + if(m_handler->state() == Qmmp::Stopped) + m_handler->dispatch(Qmmp::Buffering); + return true; } void SoundCore::stop() { qApp->sendPostedEvents(this, 0); m_url.clear(); - if(m_pendingEngine) - delete m_pendingEngine; - m_pendingEngine = 0; if(m_engine) { m_engine->stop(); qApp->sendPostedEvents(this, 0); + //m_engine->deleteLater(); + //m_engine = 0; } - qDeleteAll(m_pendingSources); - m_pendingSources.clear(); + qDeleteAll(m_sources); + m_sources.clear(); + m_nextState = NO_ENGINE; updateVolume(); if(state() == Qmmp::NormalError || state() == Qmmp::FatalError || state() == Qmmp::Buffering) StateHandler::instance()->dispatch(Qmmp::Stopped); //clear error and buffering state @@ -131,11 +125,16 @@ void SoundCore::seek(qint64 pos) m_engine->seek(pos); } -const QString SoundCore::url() +const QString SoundCore::url() const { return m_url; } +bool SoundCore::nextTrackAccepted() const +{ + return m_nextState == SAME_ENGINE; +} + qint64 SoundCore::totalTime() const { return (m_engine) ? m_engine->totalTime() : 0; @@ -220,34 +219,21 @@ QString SoundCore::metaData(Qmmp::MetaData key) return m_metaData[key]; } -bool SoundCore::enqueue() +void SoundCore::startNextSource() { - InputSource *s = qobject_cast<InputSource*>(sender()); - if(!s) - { - qWarning("SoundCore: unknown signal source"); - return false; - } + if(m_sources.isEmpty()) + return; - m_pendingSources.removeAll(s); + InputSource *s = m_sources.dequeue(); m_url = s->url(); - if(s->ioDevice()) + if(s->ioDevice() && !s->ioDevice()->open(QIODevice::ReadOnly)) { - bool ok = s->ioDevice()->open(QIODevice::ReadOnly); - if(!ok) - { - qWarning("SoundCore: input error: %s", qPrintable(s->ioDevice()->errorString())); - m_url.clear(); - s->deleteLater(); - if(state() == Qmmp::Stopped || state() == Qmmp::Buffering) - { - m_handler->dispatch(Qmmp::NormalError); - } - else - m_error = true; - return false; - } + qWarning("SoundCore: input error: %s", qPrintable(s->ioDevice()->errorString())); + m_url.clear(); + s->deleteLater(); + m_nextState = INVALID_SOURCE; + return; } if(!m_engine) @@ -255,72 +241,61 @@ bool SoundCore::enqueue() if((m_engine = AbstractEngine::create(s, this))) { m_engine->play(); - m_handler->setCurrentEngine(m_engine); - return true; + m_nextState = NO_ENGINE; + return; } else { s->deleteLater(); - m_handler->setCurrentEngine(0); m_handler->dispatch(Qmmp::NormalError); - return false; + return; } } - - if(m_engine->enqueue(s)) + else if(m_engine->enqueue(s)) { if(state() == Qmmp::Stopped || state() == Qmmp::Buffering) + { m_engine->play(); + m_nextState = NO_ENGINE; + } else - m_handler->setNextEngine(m_engine); - m_handler->setCurrentEngine(m_engine); + { + m_nextState = SAME_ENGINE; + } } else { - AbstractEngine *engine = AbstractEngine::create(s, this); - if(!engine) - { - s->deleteLater(); - m_handler->setCurrentEngine(0); - if(state() == Qmmp::Stopped || state() == Qmmp::Buffering) - m_handler->dispatch(Qmmp::NormalError); - else - m_error = true; - return false; - } - if (m_handler->state() == Qmmp::Playing || m_handler->state() == Qmmp::Paused) - { - if(m_pendingEngine) - m_pendingEngine->deleteLater(); - m_pendingEngine = engine; - m_handler->setNextEngine(engine); - } - else + m_sources.prepend(s); //try for next engine + if(s->ioDevice()) + s->ioDevice()->close(); + m_nextState = ANOTHER_ENGINE; + if(state() == Qmmp::Stopped || state() == Qmmp::Buffering) { - m_engine->deleteLater(); - m_engine = engine; - m_engine->play(); - m_handler->setCurrentEngine(m_engine); - m_pendingEngine = 0; + startNextEngine(); } } - return true; } -void SoundCore::startPendingEngine() +void SoundCore::startNextEngine() { - if(state() == Qmmp::Stopped && m_pendingEngine) + switch(m_nextState) { + case NO_ENGINE: + case SAME_ENGINE: + break; + case ANOTHER_ENGINE: if(m_engine) - delete m_engine; - m_engine = m_pendingEngine; - m_pendingEngine = 0; - m_engine->play(); - m_handler->setCurrentEngine(m_engine); - } - else if(state() == Qmmp::Stopped && m_error) - { - m_error = false; + { + m_engine->deleteLater(); + m_engine = 0; + } + if(!m_sources.isEmpty()) + { + m_handler->dispatch(Qmmp::Buffering); + startNextSource(); + } + break; + case INVALID_SOURCE: m_handler->dispatch(Qmmp::NormalError); } } @@ -334,8 +309,10 @@ bool SoundCore::event(QEvent *e) { if(e->type() == EVENT_STATE_CHANGED) { - emit stateChanged(((StateChangedEvent *) e)->currentState()); - startPendingEngine(); + Qmmp::State st = ((StateChangedEvent *) e)->currentState(); + emit stateChanged(st); + if(st == Qmmp::Stopped) + startNextEngine(); } else if(e->type() == EVENT_METADATA_CHANGED) { diff --git a/src/qmmp/soundcore.h b/src/qmmp/soundcore.h index 8e2633aae..8c5896b14 100644 --- a/src/qmmp/soundcore.h +++ b/src/qmmp/soundcore.h @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 2006-2010 by Ilya Kotov * + * Copyright (C) 2006-2011 by Ilya Kotov * * forkotov02@hotmail.ru * * * * This program is free software; you can redistribute it and/or modify * @@ -22,6 +22,7 @@ #include <QObject> #include <QString> +#include <QQueue> #include "decoder.h" #include "output.h" #include "visual.h" @@ -62,7 +63,6 @@ public: * Chages equalizer settings to \b settings. */ void setEqSettings(const EqSettings &settings); - /*! * Returns left volume level. */ @@ -136,7 +136,12 @@ public slots: /*! * This function returns file path or stream url. */ - const QString url(); + const QString url() const; + /*! + * Indicates that the current active engine will be used for the next queued track. + * May be useful for some effect plugins. + */ + bool nextTrackAccepted() const; signals: /*! @@ -197,24 +202,30 @@ signals: void nextTrackRequest(); private slots: - bool enqueue(); - void startPendingEngine(); + void startNextSource(); + void startNextEngine(); void updateVolume(); private: bool event(QEvent *e); + enum NextEngineState + { + NO_ENGINE = 0, + SAME_ENGINE, + ANOTHER_ENGINE, + INVALID_SOURCE + }; QMap <Qmmp::MetaData, QString> m_metaData; Decoder* m_decoder; QString m_url; - bool m_error; QList <Visual*> m_visuals; QWidget *m_parentWidget; static SoundCore* m_instance; StateHandler *m_handler; VolumeControl *m_volumeControl; AbstractEngine *m_engine; - AbstractEngine *m_pendingEngine; - QList<InputSource *> m_pendingSources; + QQueue<InputSource *> m_sources; + int m_nextState; }; #endif diff --git a/src/qmmp/statehandler.cpp b/src/qmmp/statehandler.cpp index eb5d3508d..fca37893b 100644 --- a/src/qmmp/statehandler.cpp +++ b/src/qmmp/statehandler.cpp @@ -42,8 +42,6 @@ StateHandler::StateHandler(QObject *parent) m_channels = 0; m_sendAboutToFinish = true; m_state = Qmmp::Stopped; - m_next_engine = 0; - m_current_engine = 0; } @@ -137,7 +135,6 @@ void StateHandler::dispatch(Qmmp::State state) m_frequency = 0; m_precision = 0; m_channels = 0; - m_next_engine = 0; m_metaData.clear(); m_sendAboutToFinish = true; } @@ -168,16 +165,6 @@ void StateHandler::dispatchBuffer(int percent) emit bufferingProgress(percent); } -void StateHandler::setNextEngine(AbstractEngine *engine) -{ - m_next_engine = engine; -} - -void StateHandler::setCurrentEngine(AbstractEngine *engine) -{ - m_current_engine = engine; -} - qint64 StateHandler::elapsed() { return m_elapsed; @@ -224,16 +211,6 @@ void StateHandler::sendFinished() qApp->postEvent(parent(), new QEvent(EVENT_FINISHED)); } -AbstractEngine *StateHandler::nextEngine() -{ - return m_next_engine; -} - -AbstractEngine *StateHandler::currentEngine() -{ - return m_current_engine; -} - StateHandler *StateHandler::instance() { return m_instance; diff --git a/src/qmmp/statehandler.h b/src/qmmp/statehandler.h index b8c1ab9e4..9c8d2fd89 100644 --- a/src/qmmp/statehandler.h +++ b/src/qmmp/statehandler.h @@ -69,14 +69,6 @@ public: */ virtual void dispatchBuffer(int percent); /*! - * Sets next audio engine. - */ - void setNextEngine(AbstractEngine *engine); - /*! - * Sets current audio engine. - */ - void setCurrentEngine(AbstractEngine *engine); - /*! * Returns the current time (in milliseconds). */ qint64 elapsed(); @@ -106,17 +98,6 @@ public: void sendNextTrackRequest(); void sendFinished(); /*! - * Returns a pointer to the audio engine which will be used to play next (queued) audio source. - * Otherwise returns \b 0 - */ - AbstractEngine *nextEngine(); - /*! - * Returns a pointer to the current audio engine. - * Otherwise returns \b 0 - */ - AbstractEngine *currentEngine(); - - /*! * Returns a pointer to the first created StateHandler instance. */ static StateHandler* instance(); @@ -164,8 +145,6 @@ private: QMap <Qmmp::MetaData, QString> m_cachedMetaData; Qmmp::State m_state; QMutex m_mutex; - AbstractEngine *m_next_engine; - AbstractEngine *m_current_engine; }; #endif |
