aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/plugins/Effect/crossfade/crossfadeplugin.cpp2
-rw-r--r--src/qmmp/soundcore.cpp167
-rw-r--r--src/qmmp/soundcore.h27
-rw-r--r--src/qmmp/statehandler.cpp23
-rw-r--r--src/qmmp/statehandler.h21
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