summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/phonon
diff options
context:
space:
mode:
authoraxis <qt-info@nokia.com>2010-01-21 12:20:33 (GMT)
committeraxis <qt-info@nokia.com>2010-01-21 12:20:33 (GMT)
commit833bea1f71ed685e5f371d93f6f5c2da7be546e5 (patch)
tree09e3f60311ebf8af123a9e61f27908dd87118109 /src/3rdparty/phonon
parentd609f7d1963e06d05fa6f7e4a098a304a177bc68 (diff)
parentd83e82e5c8a7fa0f6b1dcc4b1ab56f22afd942f6 (diff)
downloadQt-833bea1f71ed685e5f371d93f6f5c2da7be546e5.zip
Qt-833bea1f71ed685e5f371d93f6f5c2da7be546e5.tar.gz
Qt-833bea1f71ed685e5f371d93f6f5c2da7be546e5.tar.bz2
Merge branch '4.6' of scm.dev.nokia.troll.no:qt/qt-s60-public
Conflicts: mkspecs/features/symbian/platform_paths.prf
Diffstat (limited to 'src/3rdparty/phonon')
-rw-r--r--src/3rdparty/phonon/mmf/abstractaudioeffect.cpp152
-rw-r--r--src/3rdparty/phonon/mmf/abstractaudioeffect.h86
-rw-r--r--src/3rdparty/phonon/mmf/abstractmediaplayer.cpp226
-rw-r--r--src/3rdparty/phonon/mmf/abstractmediaplayer.h41
-rw-r--r--src/3rdparty/phonon/mmf/abstractplayer.cpp34
-rw-r--r--src/3rdparty/phonon/mmf/abstractplayer.h40
-rw-r--r--src/3rdparty/phonon/mmf/audioequalizer.cpp101
-rw-r--r--src/3rdparty/phonon/mmf/audioequalizer.h22
-rw-r--r--src/3rdparty/phonon/mmf/audiooutput.cpp13
-rw-r--r--src/3rdparty/phonon/mmf/audiooutput.h4
-rw-r--r--src/3rdparty/phonon/mmf/audioplayer.cpp99
-rw-r--r--src/3rdparty/phonon/mmf/audioplayer.h59
-rw-r--r--src/3rdparty/phonon/mmf/backend.cpp40
-rw-r--r--src/3rdparty/phonon/mmf/backend.h6
-rw-r--r--src/3rdparty/phonon/mmf/bassboost.cpp26
-rw-r--r--src/3rdparty/phonon/mmf/bassboost.h24
-rw-r--r--src/3rdparty/phonon/mmf/dummyplayer.cpp19
-rw-r--r--src/3rdparty/phonon/mmf/dummyplayer.h8
-rw-r--r--src/3rdparty/phonon/mmf/effectfactory.cpp223
-rw-r--r--src/3rdparty/phonon/mmf/effectfactory.h51
-rw-r--r--src/3rdparty/phonon/mmf/effectparameter.cpp71
-rw-r--r--src/3rdparty/phonon/mmf/effectparameter.h74
-rw-r--r--src/3rdparty/phonon/mmf/environmentalreverb.cpp201
-rw-r--r--src/3rdparty/phonon/mmf/environmentalreverb.h62
-rw-r--r--src/3rdparty/phonon/mmf/loudness.cpp58
-rw-r--r--src/3rdparty/phonon/mmf/loudness.h60
-rw-r--r--src/3rdparty/phonon/mmf/mediaobject.cpp94
-rw-r--r--src/3rdparty/phonon/mmf/mediaobject.h26
-rw-r--r--src/3rdparty/phonon/mmf/mmf_medianode.cpp153
-rw-r--r--src/3rdparty/phonon/mmf/mmf_medianode.h78
-rw-r--r--src/3rdparty/phonon/mmf/mmf_videoplayer.cpp104
-rw-r--r--src/3rdparty/phonon/mmf/mmf_videoplayer.h41
-rw-r--r--src/3rdparty/phonon/mmf/objectdump.cpp2
-rw-r--r--src/3rdparty/phonon/mmf/stereowidening.cpp93
-rw-r--r--src/3rdparty/phonon/mmf/stereowidening.h62
-rw-r--r--src/3rdparty/phonon/mmf/utils.cpp96
-rw-r--r--src/3rdparty/phonon/mmf/utils.h25
-rw-r--r--src/3rdparty/phonon/mmf/videooutput.h2
-rw-r--r--src/3rdparty/phonon/mmf/videowidget.cpp14
-rw-r--r--src/3rdparty/phonon/mmf/videowidget.h8
-rw-r--r--src/3rdparty/phonon/phonon/effectwidget.cpp4
41 files changed, 1924 insertions, 678 deletions
diff --git a/src/3rdparty/phonon/mmf/abstractaudioeffect.cpp b/src/3rdparty/phonon/mmf/abstractaudioeffect.cpp
index a559249..132eb79 100644
--- a/src/3rdparty/phonon/mmf/abstractaudioeffect.cpp
+++ b/src/3rdparty/phonon/mmf/abstractaudioeffect.cpp
@@ -19,6 +19,8 @@ along with this library. If not, see <http://www.gnu.org/licenses/>.
#include "mediaobject.h"
#include "abstractaudioeffect.h"
+#include "audioplayer.h"
+#include "mmf_videoplayer.h"
QT_BEGIN_NAMESPACE
@@ -34,24 +36,25 @@ using namespace Phonon::MMF;
*/
AbstractAudioEffect::AbstractAudioEffect(QObject *parent,
- const QList<EffectParameter> &params) : MediaNode::MediaNode(parent)
- , m_params(params)
+ const QList<EffectParameter> &params)
+ : MediaNode(parent)
+ , m_params(params)
+ , m_player(0)
{
-}
-bool AbstractAudioEffect::disconnectMediaNode(MediaNode *target)
-{
- MediaNode::disconnectMediaNode(target);
- m_effect.reset();
- return true;
}
-QList<EffectParameter> AbstractAudioEffect::parameters() const
+QList<Phonon::EffectParameter> AbstractAudioEffect::parameters() const
{
- return m_params;
+ // Convert from QList<MMF::EffectParameter> to QList<Phonon::EffectParameter>
+ QList<Phonon::EffectParameter> result;
+ EffectParameter param;
+ foreach (param, m_params)
+ result += param;
+ return result;
}
-QVariant AbstractAudioEffect::parameterValue(const EffectParameter &queriedParam) const
+QVariant AbstractAudioEffect::parameterValue(const Phonon::EffectParameter &queriedParam) const
{
const QVariant &val = m_values.value(queriedParam.id());
@@ -61,22 +64,131 @@ QVariant AbstractAudioEffect::parameterValue(const EffectParameter &queriedParam
return val;
}
-bool AbstractAudioEffect::activateOnMediaObject(MediaObject *mo)
+void AbstractAudioEffect::setParameterValue(const Phonon::EffectParameter &param,
+ const QVariant &newValue)
+{
+ m_values.insert(param.id(), newValue);
+
+ if (m_effect.data()) {
+ const EffectParameter& internalParam = internalParameter(param.id());
+ int err = parameterChanged(internalParam, newValue);
+ // TODO: handle audio effect errors
+ Q_UNUSED(err);
+ }
+}
+
+void AbstractAudioEffect::abstractPlayerChanged(AbstractPlayer *player)
+{
+ m_player = qobject_cast<AbstractMediaPlayer *>(player);
+ m_effect.reset();
+}
+
+void AbstractAudioEffect::stateChanged(Phonon::State newState,
+ Phonon::State oldState)
+{
+ if (Phonon::LoadingState == oldState
+ && Phonon::LoadingState != newState)
+ createEffect();
+}
+
+void AbstractAudioEffect::connectMediaObject(MediaObject *mediaObject)
{
- AudioPlayer *const ap = qobject_cast<AudioPlayer *>(mo->abstractPlayer());
+ Q_ASSERT_X(!m_player, Q_FUNC_INFO, "Player already connected");
+ Q_ASSERT_X(!m_effect.data(), Q_FUNC_INFO, "Effect already created");
+
+ abstractPlayerChanged(mediaObject->abstractPlayer());
+
+ connect(mediaObject, SIGNAL(stateChanged(Phonon::State, Phonon::State)),
+ SLOT(stateChanged(Phonon::State, Phonon::State)));
- if (ap)
- return activateOn(ap->player());
+ connect(mediaObject, SIGNAL(abstractPlayerChanged(AbstractPlayer *)),
+ SLOT(abstractPlayerChanged(AbstractPlayer *)));
+
+ if (mediaObject->state() != Phonon::LoadingState)
+ createEffect();
+}
+
+void AbstractAudioEffect::disconnectMediaObject(MediaObject *mediaObject)
+{
+ mediaObject->disconnect(this);
+ abstractPlayerChanged(0);
+}
+
+void AbstractAudioEffect::setEnabled(bool enabled)
+{
+ TInt err = KErrNone;
+
+ if (enabled)
+ // TODO: handle audio effect errors
+ TRAP(err, m_effect->EnableL())
else
- return true;
+ // TODO: handle audio effect errors
+ TRAP(err, m_effect->DisableL())
+
+ Q_UNUSED(err);
}
-void AbstractAudioEffect::setParameterValue(const EffectParameter &param,
- const QVariant &newValue)
+void AbstractAudioEffect::createEffect()
{
- m_values.insert(param.id(), newValue);
- parameterChanged(param.id(), newValue);
+ Q_ASSERT_X(m_player, Q_FUNC_INFO, "Invalid media player pointer");
+
+ if (AudioPlayer *audioPlayer = qobject_cast<AudioPlayer *>(m_player)) {
+ createEffect(audioPlayer->nativePlayer());
+ }
+
+ if (m_effect.data()) {
+ EffectParameter param;
+ int err = 0;
+ foreach (param, m_params) {
+ const QVariant value = parameterValue(param);
+ err = parameterChanged(param, value);
+ }
+ Q_UNUSED(err)
+ }
}
+const MMF::EffectParameter& AbstractAudioEffect::internalParameter(int id) const
+{
+ const EffectParameter *result = 0;
+ for (int i=0; i<m_params.count() && !result; ++i) {
+ if (m_params[i].id() == id)
+ result = &m_params[i];
+ }
+ Q_ASSERT_X(result, Q_FUNC_INFO, "Parameter not found");
+ return *result;
+}
+
+int AbstractAudioEffect::parameterChanged(const EffectParameter &param,
+ const QVariant &value)
+{
+ int err = 0;
+
+ switch (param.id()) {
+ case ParameterEnable:
+ setEnabled(value.toBool());
+ break;
+ default:
+ {
+ const EffectParameter& internalParam = internalParameter(param.id());
+ err = effectParameterChanged(internalParam, value);
+ }
+ break;
+ }
+
+ if (!err)
+ TRAP(err, m_effect->ApplyL());
+
+ return err;
+}
+
+int AbstractAudioEffect::effectParameterChanged(
+ const EffectParameter &param, const QVariant &value)
+{
+ // Default implementation
+ Q_ASSERT_X(false, Q_FUNC_INFO, "Effect has no parameters");
+ return 0;
+}
+
+
QT_END_NAMESPACE
diff --git a/src/3rdparty/phonon/mmf/abstractaudioeffect.h b/src/3rdparty/phonon/mmf/abstractaudioeffect.h
index 01542c9..436e8e4 100644
--- a/src/3rdparty/phonon/mmf/abstractaudioeffect.h
+++ b/src/3rdparty/phonon/mmf/abstractaudioeffect.h
@@ -19,15 +19,18 @@ along with this library. If not, see <http://www.gnu.org/licenses/>.
#ifndef PHONON_MMF_ABSTRACTEFFECT_H
#define PHONON_MMF_ABSTRACTEFFECT_H
-#include "mmf_medianode.h"
-
#include <QScopedPointer>
#include <AudioEffectBase.h>
-#include <Phonon/EffectInterface>
-#include <Phonon/EffectParameter>
+#include <phonon/effectinterface.h>
+
#include "audioplayer.h"
+#include "effectparameter.h"
+#include "mmf_medianode.h"
+#include "mmf_videoplayer.h"
+
+class CMdaAudioOutputStream;
QT_BEGIN_NAMESPACE
@@ -35,6 +38,8 @@ namespace Phonon
{
namespace MMF
{
+class AbstractPlayer;
+class AbstractMediaPlayer;
/**
* @short Base class for all effects for MMF.
@@ -61,42 +66,71 @@ public:
AbstractAudioEffect(QObject *parent,
const QList<EffectParameter> &params);
- virtual QList<EffectParameter> parameters() const;
- virtual QVariant parameterValue(const EffectParameter &param) const;
- virtual void setParameterValue(const EffectParameter &,
+ // Phonon::EffectInterface
+ virtual QList<Phonon::EffectParameter> parameters() const;
+ virtual QVariant parameterValue(const Phonon::EffectParameter &param) const;
+ virtual void setParameterValue(const Phonon::EffectParameter &,
const QVariant &newValue);
- virtual bool disconnectMediaNode(MediaNode *target);
-
- enum Type
+ // Parameters which are shared by all effects
+ enum CommonParameters
{
- EffectAudioEqualizer = 1,
- EffectBassBoost,
- EffectDistanceAttenuation,
- EffectEnvironmentalReverb,
- EffectListenerOrientation,
- EffectLoudness,
- EffectSourceOrientation,
- EffectStereoWidening
+ ParameterEnable = 0,
+ ParameterBase // must be last entry in enum
};
+public Q_SLOTS:
+ void abstractPlayerChanged(AbstractPlayer *player);
+ void stateChanged(Phonon::State newState,
+ Phonon::State oldState);
+
protected:
- virtual bool activateOn(CPlayerType *player) = 0;
- virtual void parameterChanged(const int id,
- const QVariant &value) = 0;
+ // MediaNode
+ void connectMediaObject(MediaObject *mediaObject);
+ void disconnectMediaObject(MediaObject *mediaObject);
+
+ virtual void createEffect(AudioPlayer::NativePlayer *player) = 0;
- /**
- * Part of the implementation of AbstractAudioEffect. Forwards the call to
- * activateOn(), essentially.
- */
- virtual bool activateOnMediaObject(MediaObject *mo);
+ // Effect-specific parameter changed
+ virtual int effectParameterChanged(const EffectParameter &param,
+ const QVariant &value);
+private:
+ void createEffect();
+ void setEnabled(bool enabled);
+ const EffectParameter& internalParameter(int id) const;
+ int parameterChanged(const EffectParameter &param,
+ const QVariant &value);
+
+protected:
QScopedPointer<CAudioEffect> m_effect;
+
private:
const QList<EffectParameter> m_params;
+ AbstractMediaPlayer * m_player;
QHash<int, QVariant> m_values;
};
+
+}
}
+
+
+// Macro for defining functions which depend on the native class name
+// for each of the effects. Using this reduces repetition of boilerplate
+// in the implementations of the backend effect nodes.
+
+#define PHONON_MMF_DEFINE_EFFECT_FUNCTIONS(Effect) \
+ \
+void Effect##::createEffect(AudioPlayer::NativePlayer *player) \
+{ \
+ C##Effect *ptr = 0; \
+ QT_TRAP_THROWING(ptr = C##Effect::NewL(*player)); \
+ m_effect.reset(ptr); \
+} \
+ \
+C##Effect* Effect::concreteEffect() \
+{ \
+ return static_cast<C##Effect *>(m_effect.data()); \
}
QT_END_NAMESPACE
diff --git a/src/3rdparty/phonon/mmf/abstractmediaplayer.cpp b/src/3rdparty/phonon/mmf/abstractmediaplayer.cpp
index 99e96cd..544762a 100644
--- a/src/3rdparty/phonon/mmf/abstractmediaplayer.cpp
+++ b/src/3rdparty/phonon/mmf/abstractmediaplayer.cpp
@@ -20,6 +20,7 @@ along with this library. If not, see <http://www.gnu.org/licenses/>.
#include "abstractmediaplayer.h"
#include "defs.h"
+#include "mediaobject.h"
#include "utils.h"
QT_BEGIN_NAMESPACE
@@ -36,27 +37,26 @@ using namespace Phonon::MMF;
//-----------------------------------------------------------------------------
const int NullMaxVolume = -1;
+const int BufferStatusTimerInterval = 100; // ms
//-----------------------------------------------------------------------------
// Constructor / destructor
//-----------------------------------------------------------------------------
-MMF::AbstractMediaPlayer::AbstractMediaPlayer() :
- m_playPending(false)
- , m_tickTimer(new QTimer(this))
- , m_mmfMaxVolume(NullMaxVolume)
-{
- connect(m_tickTimer.data(), SIGNAL(timeout()), this, SLOT(tick()));
-}
-
-MMF::AbstractMediaPlayer::AbstractMediaPlayer(const AbstractPlayer& player) :
- AbstractPlayer(player)
+MMF::AbstractMediaPlayer::AbstractMediaPlayer
+ (MediaObject *parent, const AbstractPlayer *player)
+ : AbstractPlayer(player)
+ , m_parent(parent)
, m_playPending(false)
- , m_tickTimer(new QTimer(this))
+ , m_positionTimer(new QTimer(this))
+ , m_bufferStatusTimer(new QTimer(this))
, m_mmfMaxVolume(NullMaxVolume)
+ , m_prefinishMarkSent(false)
+ , m_aboutToFinishSent(false)
{
- connect(m_tickTimer.data(), SIGNAL(timeout()), this, SLOT(tick()));
+ connect(m_positionTimer.data(), SIGNAL(timeout()), this, SLOT(positionTick()));
+ connect(m_bufferStatusTimer.data(), SIGNAL(timeout()), this, SLOT(bufferStatusTick()));
}
//-----------------------------------------------------------------------------
@@ -70,7 +70,7 @@ void MMF::AbstractMediaPlayer::play()
switch (privateState()) {
case GroundState:
- setError(NormalError);
+ setError(tr("Not ready to play"));
break;
case LoadingState:
@@ -80,7 +80,7 @@ void MMF::AbstractMediaPlayer::play()
case StoppedState:
case PausedState:
doPlay();
- startTickTimer();
+ startPositionTimer();
changeState(PlayingState);
break;
@@ -104,21 +104,22 @@ void MMF::AbstractMediaPlayer::pause()
TRACE_ENTRY("state %d", privateState());
m_playPending = false;
+ stopTimers();
switch (privateState()) {
case GroundState:
case LoadingState:
case PausedState:
+ case StoppedState:
// Do nothing
break;
- case StoppedState:
case PlayingState:
- case ErrorState:
case BufferingState:
- doPause();
- stopTickTimer();
changeState(PausedState);
+ // Fall through
+ case ErrorState:
+ doPause();
break;
// Protection against adding new states and forgetting to update this switch
@@ -135,6 +136,7 @@ void MMF::AbstractMediaPlayer::stop()
TRACE_ENTRY("state %d", privateState());
m_playPending = false;
+ stopTimers();
switch (privateState()) {
case GroundState:
@@ -148,7 +150,6 @@ void MMF::AbstractMediaPlayer::stop()
case BufferingState:
case PausedState:
doStop();
- stopTickTimer();
changeState(StoppedState);
break;
@@ -173,14 +174,21 @@ void MMF::AbstractMediaPlayer::seek(qint64 ms)
case PlayingState:
case LoadingState:
{
- const bool tickTimerWasRunning = m_tickTimer->isActive();
- stopTickTimer();
+ bool wasPlaying = false;
+ if (state() == PlayingState) {
+ stopPositionTimer();
+ doPause();
+ wasPlaying = true;
+ }
doSeek(ms);
+ resetMarksIfRewound();
- if (tickTimerWasRunning) {
- startTickTimer();
+ if(wasPlaying && state() != ErrorState) {
+ doPlay();
+ startPositionTimer();
}
+
break;
}
case BufferingState:
@@ -203,17 +211,12 @@ void MMF::AbstractMediaPlayer::doSetTickInterval(qint32 interval)
TRACE_CONTEXT(AbstractMediaPlayer::doSetTickInterval, EAudioApi);
TRACE_ENTRY("state %d m_interval %d interval %d", privateState(), tickInterval(), interval);
- m_tickTimer->setInterval(interval);
+ m_positionTimer->setInterval(interval);
TRACE_EXIT_0();
}
-MediaSource MMF::AbstractMediaPlayer::source() const
-{
- return m_source;
-}
-
-void MMF::AbstractMediaPlayer::setFileSource(const MediaSource &source, RFile& file)
+void MMF::AbstractMediaPlayer::open(const MediaSource &source, RFile& file)
{
TRACE_CONTEXT(AbstractMediaPlayer::setFileSource, EAudioApi);
TRACE_ENTRY("state %d source.type %d", privateState(), source.type());
@@ -221,15 +224,14 @@ void MMF::AbstractMediaPlayer::setFileSource(const MediaSource &source, RFile& f
close();
changeState(GroundState);
- // TODO: is it correct to assign even if the media type is not supported in
- // the switch statement below?
- m_source = source;
-
TInt symbianErr = KErrNone;
+ QString errorMessage;
- switch (m_source.type()) {
+ switch (source.type()) {
case MediaSource::LocalFile: {
symbianErr = openFile(file);
+ if (KErrNone != symbianErr)
+ errorMessage = tr("Error opening file");
break;
}
@@ -238,68 +240,76 @@ void MMF::AbstractMediaPlayer::setFileSource(const MediaSource &source, RFile& f
if (url.scheme() == QLatin1String("file")) {
symbianErr = openFile(file);
- }
- else {
- TRACE_0("Source type not supported");
- // TODO: support network URLs
- symbianErr = KErrNotSupported;
+ if (KErrNone != symbianErr)
+ errorMessage = tr("Error opening file");
+ } else {
+ symbianErr = openUrl(url.toString());
+ if (KErrNone != symbianErr)
+ errorMessage = tr("Error opening URL");
}
break;
}
- case MediaSource::Invalid:
- case MediaSource::Disc:
- case MediaSource::Stream:
- TRACE_0("Source type not supported");
- symbianErr = KErrNotSupported;
- break;
-
- case MediaSource::Empty:
- TRACE_0("Empty source - doing nothing");
- TRACE_EXIT_0();
- return;
+ // Other source types are handled in MediaObject::createPlayer
- // Protection against adding new media types and forgetting to update this switch
+ // Protection against adding new media types and forgetting to update this switch
default:
TRACE_PANIC(InvalidMediaTypePanic);
}
- if (KErrNone == symbianErr) {
+ if (errorMessage.isEmpty()) {
changeState(LoadingState);
} else {
- TRACE("error %d", symbianErr)
- setError(NormalError);
+ if (symbianErr)
+ setError(errorMessage, symbianErr);
+ else
+ setError(errorMessage);
}
TRACE_EXIT_0();
}
-void MMF::AbstractMediaPlayer::setNextSource(const MediaSource &source)
+void MMF::AbstractMediaPlayer::volumeChanged(qreal volume)
{
- TRACE_CONTEXT(AbstractMediaPlayer::setNextSource, EAudioApi);
+ TRACE_CONTEXT(AbstractMediaPlayer::volumeChanged, EAudioInternal);
TRACE_ENTRY("state %d", privateState());
- // TODO: handle 'next source'
-
- m_nextSource = source;
- Q_UNUSED(source);
+ AbstractPlayer::volumeChanged(volume);
+ doVolumeChanged();
TRACE_EXIT_0();
}
+//-----------------------------------------------------------------------------
+// Private functions
+//-----------------------------------------------------------------------------
-void MMF::AbstractMediaPlayer::volumeChanged(qreal volume)
+void MMF::AbstractMediaPlayer::startPositionTimer()
{
- TRACE_CONTEXT(AbstractMediaPlayer::volumeChanged, EAudioInternal);
- TRACE_ENTRY("state %d", privateState());
+ m_positionTimer->start(tickInterval());
+}
- AbstractPlayer::volumeChanged(volume);
- doVolumeChanged();
+void MMF::AbstractMediaPlayer::stopPositionTimer()
+{
+ m_positionTimer->stop();
+}
- TRACE_EXIT_0();
+void MMF::AbstractMediaPlayer::startBufferStatusTimer()
+{
+ m_bufferStatusTimer->start(BufferStatusTimerInterval);
}
+void MMF::AbstractMediaPlayer::stopBufferStatusTimer()
+{
+ m_bufferStatusTimer->stop();
+}
+
+void MMF::AbstractMediaPlayer::stopTimers()
+{
+ stopPositionTimer();
+ stopBufferStatusTimer();
+}
void MMF::AbstractMediaPlayer::doVolumeChanged()
{
@@ -318,7 +328,7 @@ void MMF::AbstractMediaPlayer::doVolumeChanged()
const int err = setDeviceVolume(volume);
if (KErrNone != err) {
- setError(NormalError);
+ setError(tr("Setting volume failed"), err);
}
break;
}
@@ -330,19 +340,23 @@ void MMF::AbstractMediaPlayer::doVolumeChanged()
}
}
-
//-----------------------------------------------------------------------------
// Protected functions
//-----------------------------------------------------------------------------
-void MMF::AbstractMediaPlayer::startTickTimer()
+void MMF::AbstractMediaPlayer::bufferingStarted()
{
- m_tickTimer->start(tickInterval());
+ m_stateBeforeBuffering = privateState();
+ changeState(BufferingState);
+ bufferStatusTick();
+ startBufferStatusTimer();
}
-void MMF::AbstractMediaPlayer::stopTickTimer()
+void MMF::AbstractMediaPlayer::bufferingComplete()
{
- m_tickTimer->stop();
+ stopBufferStatusTimer();
+ emit MMF::AbstractPlayer::bufferStatus(100);
+ changeState(m_stateBeforeBuffering);
}
void MMF::AbstractMediaPlayer::maxVolumeChanged(int mmfMaxVolume)
@@ -351,6 +365,23 @@ void MMF::AbstractMediaPlayer::maxVolumeChanged(int mmfMaxVolume)
doVolumeChanged();
}
+void MMF::AbstractMediaPlayer::playbackComplete(int error)
+{
+ stopTimers();
+
+ if (KErrNone == error) {
+ changeState(StoppedState);
+
+ // MediaObject::switchToNextSource deletes the current player, so we
+ // call it via delayed slot invokation to ensure that this object does
+ // not get deleted during execution of a member function.
+ QMetaObject::invokeMethod(m_parent, "switchToNextSource", Qt::QueuedConnection);
+ }
+ else {
+ setError(tr("Playback complete"), error);
+ }
+}
+
qint64 MMF::AbstractMediaPlayer::toMilliSeconds(const TTimeIntervalMicroSeconds &in)
{
return in.Int64() / 1000;
@@ -360,10 +391,53 @@ qint64 MMF::AbstractMediaPlayer::toMilliSeconds(const TTimeIntervalMicroSeconds
// Slots
//-----------------------------------------------------------------------------
-void MMF::AbstractMediaPlayer::tick()
+void MMF::AbstractMediaPlayer::positionTick()
+{
+ emitMarksIfReached();
+
+ const qint64 current = currentTime();
+ emit MMF::AbstractPlayer::tick(current);
+}
+
+void MMF::AbstractMediaPlayer::emitMarksIfReached()
+{
+ const qint64 current = currentTime();
+ const qint64 total = totalTime();
+ const qint64 remaining = total - current;
+
+ if (prefinishMark() && !m_prefinishMarkSent) {
+ if (remaining < (prefinishMark() + tickInterval()/2)) {
+ m_prefinishMarkSent = true;
+ emit prefinishMarkReached(remaining);
+ }
+ }
+
+ if (!m_aboutToFinishSent) {
+ if (remaining < tickInterval()) {
+ m_aboutToFinishSent = true;
+ emit aboutToFinish();
+ }
+ }
+}
+
+void MMF::AbstractMediaPlayer::resetMarksIfRewound()
+{
+ const qint64 current = currentTime();
+ const qint64 total = totalTime();
+ const qint64 remaining = total - current;
+
+ if (prefinishMark() && m_prefinishMarkSent)
+ if (remaining >= (prefinishMark() + tickInterval()/2))
+ m_prefinishMarkSent = false;
+
+ if (m_aboutToFinishSent)
+ if (remaining >= tickInterval())
+ m_aboutToFinishSent = false;
+}
+
+void MMF::AbstractMediaPlayer::bufferStatusTick()
{
- // For the MWC compiler, we need to qualify the base class.
- emit MMF::AbstractPlayer::tick(currentTime());
+ emit MMF::AbstractPlayer::bufferStatus(bufferStatus());
}
void MMF::AbstractMediaPlayer::changeState(PrivateState newState)
diff --git a/src/3rdparty/phonon/mmf/abstractmediaplayer.h b/src/3rdparty/phonon/mmf/abstractmediaplayer.h
index cb6e437..abd6bff 100644
--- a/src/3rdparty/phonon/mmf/abstractmediaplayer.h
+++ b/src/3rdparty/phonon/mmf/abstractmediaplayer.h
@@ -33,6 +33,7 @@ namespace Phonon
namespace MMF
{
class AudioOutput;
+class MediaObject;
/**
* Interface via which MMF client APIs for both audio and video can be
@@ -43,19 +44,17 @@ class AbstractMediaPlayer : public AbstractPlayer
Q_OBJECT
protected:
- AbstractMediaPlayer();
- explicit AbstractMediaPlayer(const AbstractPlayer& player);
+ AbstractMediaPlayer(MediaObject *parent, const AbstractPlayer *player);
public:
+ virtual void open(const Phonon::MediaSource&, RFile&);
+
// MediaObjectInterface
virtual void play();
virtual void pause();
virtual void stop();
virtual void seek(qint64 milliseconds);
virtual bool isSeekable() const;
- virtual MediaSource source() const;
- virtual void setFileSource(const Phonon::MediaSource&, RFile&);
- virtual void setNextSource(const MediaSource &source);
virtual void volumeChanged(qreal volume);
protected:
@@ -68,6 +67,8 @@ protected:
virtual void doSeek(qint64 pos) = 0;
virtual int setDeviceVolume(int mmfVolume) = 0;
virtual int openFile(RFile& file) = 0;
+ virtual int openUrl(const QString& url) = 0;
+ virtual int bufferStatus() const = 0;
virtual void close() = 0;
virtual void changeState(PrivateState newState);
@@ -76,23 +77,30 @@ protected:
virtual QPair<QString, QString> metaDataEntry(int index) const = 0;
protected:
- bool tickTimerRunning() const;
- void startTickTimer();
- void stopTickTimer();
+ void bufferingStarted();
+ void bufferingComplete();
void maxVolumeChanged(int maxVolume);
+ void playbackComplete(int error);
static qint64 toMilliSeconds(const TTimeIntervalMicroSeconds &);
private:
+ void startPositionTimer();
+ void stopPositionTimer();
+ void startBufferStatusTimer();
+ void stopBufferStatusTimer();
+ void stopTimers();
void doVolumeChanged();
+ void emitMarksIfReached();
+ void resetMarksIfRewound();
private Q_SLOTS:
- /**
- * Receives signal from m_tickTimer
- */
- void tick();
+ void positionTick();
+ void bufferStatusTick();
private:
+ MediaObject *const m_parent;
+
/**
* This flag is set to true if play is called when the object is
* in a Loading state. Once loading is complete, playback will
@@ -100,12 +108,15 @@ private:
*/
bool m_playPending;
- QScopedPointer<QTimer> m_tickTimer;
+ QScopedPointer<QTimer> m_positionTimer;
+
+ QScopedPointer<QTimer> m_bufferStatusTimer;
+ PrivateState m_stateBeforeBuffering;
int m_mmfMaxVolume;
- MediaSource m_source;
- MediaSource m_nextSource;
+ bool m_prefinishMarkSent;
+ bool m_aboutToFinishSent;
QMultiMap<QString, QString> m_metaData;
diff --git a/src/3rdparty/phonon/mmf/abstractplayer.cpp b/src/3rdparty/phonon/mmf/abstractplayer.cpp
index caf4092..53973eb 100644
--- a/src/3rdparty/phonon/mmf/abstractplayer.cpp
+++ b/src/3rdparty/phonon/mmf/abstractplayer.cpp
@@ -33,7 +33,7 @@ using namespace Phonon::MMF;
// Constructor / destructor
//-----------------------------------------------------------------------------
-MMF::AbstractPlayer::AbstractPlayer()
+MMF::AbstractPlayer::AbstractPlayer(const AbstractPlayer *player)
: m_videoOutput(0)
, m_volume(InitialVolume)
, m_state(GroundState)
@@ -42,19 +42,13 @@ MMF::AbstractPlayer::AbstractPlayer()
, m_transitionTime(0)
, m_prefinishMark(0)
{
-
-}
-
-MMF::AbstractPlayer::AbstractPlayer(const AbstractPlayer& player)
- : m_videoOutput(player.m_videoOutput)
- , m_volume(player.m_volume)
- , m_state(GroundState)
- , m_error(NoError)
- , m_tickInterval(player.tickInterval())
- , m_transitionTime(player.transitionTime())
- , m_prefinishMark(player.prefinishMark())
-{
-
+ if(player) {
+ m_videoOutput = player->m_videoOutput;
+ m_volume = player->m_volume;
+ m_tickInterval = player->m_tickInterval;
+ m_transitionTime = player->m_transitionTime;
+ m_prefinishMark = player->m_prefinishMark;
+ }
}
//-----------------------------------------------------------------------------
@@ -113,19 +107,23 @@ void MMF::AbstractPlayer::videoOutputChanged()
// Default behaviour is empty - overridden by VideoPlayer
}
-void MMF::AbstractPlayer::setError(Phonon::ErrorType error,
- const QString &errorMessage)
+void MMF::AbstractPlayer::setError(const QString &errorMessage)
{
TRACE_CONTEXT(AbstractPlayer::setError, EAudioInternal);
- TRACE_ENTRY("state %d error %d", m_state, error);
+ TRACE_ENTRY("state %d", m_state);
- m_error = error;
+ m_error = Phonon::NormalError;
m_errorString = errorMessage;
changeState(ErrorState);
TRACE_EXIT_0();
}
+void MMF::AbstractPlayer::setError(const QString &errorMessage, int symbianError)
+{
+ setError(errorMessage + ": " + Utils::symbianErrorToString(symbianError));
+}
+
Phonon::ErrorType MMF::AbstractPlayer::errorType() const
{
const Phonon::ErrorType result = (ErrorState == m_state)
diff --git a/src/3rdparty/phonon/mmf/abstractplayer.h b/src/3rdparty/phonon/mmf/abstractplayer.h
index 2e9cfa0..cec5568 100644
--- a/src/3rdparty/phonon/mmf/abstractplayer.h
+++ b/src/3rdparty/phonon/mmf/abstractplayer.h
@@ -19,8 +19,8 @@ along with this library. If not, see <http://www.gnu.org/licenses/>.
#ifndef PHONON_MMF_ABSTRACTPLAYER_H
#define PHONON_MMF_ABSTRACTPLAYER_H
-#include <Phonon/phononnamespace.h>
-#include <Phonon/MediaSource.h>
+#include <phonon/phononnamespace.h>
+#include <phonon/mediasource.h>
#include <QObject>
@@ -53,8 +53,9 @@ class AbstractPlayer : public QObject
Q_OBJECT
public:
- AbstractPlayer();
- explicit AbstractPlayer(const AbstractPlayer& player);
+ AbstractPlayer(const AbstractPlayer *player);
+
+ virtual void open(const Phonon::MediaSource&, RFile&) = 0;
// MediaObjectInterface (implemented)
qint32 tickInterval() const;
@@ -75,22 +76,28 @@ public:
virtual Phonon::ErrorType errorType() const;
virtual QString errorString() const;
virtual qint64 totalTime() const = 0;
- virtual Phonon::MediaSource source() const = 0;
- // This is a temporary hack to work around KErrInUse from MMF
- // client utility OpenFileL calls
- //virtual void setSource(const Phonon::MediaSource &) = 0;
- virtual void setFileSource(const Phonon::MediaSource&, RFile&) = 0;
- virtual void setNextSource(const Phonon::MediaSource &) = 0;
virtual void volumeChanged(qreal volume);
void setVideoOutput(VideoOutput* videoOutput);
/**
- * Records error and changes state to ErrorState
+ * Records error message and changes state to ErrorState
+ */
+ void setError(const QString &errorMessage);
+
+ /**
+ * Records error message and changes state to ErrorState
+ *
+ * Appends a human-readable version of symbianErrorCode to the error message,
+ * e.g.
+ * @code
+ * setError("Opening file failed", KErrPermissionDenied)
+ * @endcode
+ * results in the following error message:
+ * "Opening file failed: permission denied"
*/
- void setError(Phonon::ErrorType error,
- const QString &errorMessage = QString());
+ void setError(const QString &errorMessage, int symbianErrorCode);
Phonon::State state() const;
@@ -98,9 +105,12 @@ Q_SIGNALS:
void totalTimeChanged(qint64 length);
void finished();
void tick(qint64 time);
- void stateChanged(Phonon::State oldState,
- Phonon::State newState);
+ void bufferStatus(int percentFilled);
+ void stateChanged(Phonon::State newState,
+ Phonon::State oldState);
void metaDataChanged(const QMultiMap<QString, QString>& metaData);
+ void aboutToFinish();
+ void prefinishMarkReached(qint32 remaining);
protected:
/**
diff --git a/src/3rdparty/phonon/mmf/audioequalizer.cpp b/src/3rdparty/phonon/mmf/audioequalizer.cpp
index 7cc9bc7..1d2bbd4 100644
--- a/src/3rdparty/phonon/mmf/audioequalizer.cpp
+++ b/src/3rdparty/phonon/mmf/audioequalizer.cpp
@@ -16,6 +16,7 @@ along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <AudioEqualizerBase.h>
#include "audioequalizer.h"
QT_BEGIN_NAMESPACE
@@ -27,61 +28,79 @@ using namespace Phonon::MMF;
\internal
*/
-AudioEqualizer::AudioEqualizer(QObject *parent) : AbstractAudioEffect::AbstractAudioEffect(parent, createParams())
-{
-}
-
-void AudioEqualizer::parameterChanged(const int pid,
- const QVariant &value)
-{
- // There is no way to return an error from this function, so we just
- // have to trap and ignore exceptions.
- TRAP_IGNORE(static_cast<CAudioEqualizer *>(m_effect.data())->SetBandLevelL(pid, value.toInt()));
-}
+// Define functions which depend on concrete native effect class name
+PHONON_MMF_DEFINE_EFFECT_FUNCTIONS(AudioEqualizer)
-bool AudioEqualizer::activateOn(CPlayerType *player)
+AudioEqualizer::AudioEqualizer(QObject *parent, const QList<EffectParameter>& parameters)
+ : AbstractAudioEffect::AbstractAudioEffect(parent, parameters)
{
- CAudioEqualizer *ptr = 0;
- QT_TRAP_THROWING(ptr = CAudioEqualizer::NewL(*player));
- m_effect.reset(ptr);
- return true;
}
-QList<EffectParameter> AudioEqualizer::createParams()
+int AudioEqualizer::effectParameterChanged(const EffectParameter &param,
+ const QVariant &value)
{
- QList<EffectParameter> retval;
-
- // We temporarily create an AudioPlayer, and run the effect on it, so
- // we can extract the readonly data we need.
- AudioPlayer dummyPlayer;
+ const int band = param.id() - ParameterBase + 1;
- CAudioEqualizer *eqPtr = 0;
- QT_TRAP_THROWING(eqPtr = CAudioEqualizer::NewL(*dummyPlayer.player());)
- QScopedPointer<CAudioEqualizer> e(eqPtr);
+ const qreal externalLevel = value.toReal();
+ const int internalLevel = param.toInternalValue(externalLevel);
- TInt32 dbMin;
- TInt32 dbMax;
- e->DbLevelLimits(dbMin, dbMax);
+ TRAPD(err, concreteEffect()->SetBandLevelL(band, internalLevel));
+ return err;
+}
- const int bandCount = e->NumberOfBands();
- for (int i = 0; i < bandCount; ++i) {
- const qint32 hz = e->CenterFrequency(i);
+//-----------------------------------------------------------------------------
+// Static functions
+//-----------------------------------------------------------------------------
- const qint32 defVol = e->BandLevel(i);
+const char* AudioEqualizer::description()
+{
+ return "Audio equalizer";
+}
- retval.append(EffectParameter(i,
- tr("Frequency band, %1 Hz").arg(hz),
- EffectParameter::LogarithmicHint,
- QVariant(qint32(defVol)),
- QVariant(qint32(dbMin)),
- QVariant(qint32(dbMax)),
- QVariantList(),
- QString()));
+bool AudioEqualizer::getParameters(CMdaAudioOutputStream *stream,
+ QList<EffectParameter>& parameters)
+{
+ bool supported = false;
+
+ QScopedPointer<CAudioEqualizer> effect;
+ TRAPD(err, effect.reset(CAudioEqualizer::NewL(*stream)));
+
+ if (KErrNone == err) {
+ supported = true;
+
+ TInt32 dbMin;
+ TInt32 dbMax;
+ effect->DbLevelLimits(dbMin, dbMax);
+
+ const int bandCount = effect->NumberOfBands();
+
+ for (int i = 0; i < bandCount; ++i) {
+ // For some reason, band IDs are 1-based, as opposed to the
+ // 0-based indices used in just about other Symbian API...!
+ const int band = i + 1;
+
+ const qint32 hz = effect->CenterFrequency(band);
+
+ // We pass a floating-point parameter range of -1.0 to +1.0 for
+ // each band in order to work around a limitation in
+ // Phonon::EffectWidget. See documentation of EffectParameter
+ // for more details.
+ EffectParameter param(
+ /* parameterId */ ParameterBase + i,
+ /* name */ tr("%1 Hz").arg(hz),
+ /* hints */ EffectParameter::LogarithmicHint,
+ /* defaultValue */ QVariant(qreal(0.0)),
+ /* minimumValue */ QVariant(qreal(-1.0)),
+ /* maximumValue */ QVariant(qreal(+1.0)));
+
+ param.setInternalRange(dbMin, dbMax);
+ parameters.append(param);
+ }
}
- return retval;
+ return supported;
}
QT_END_NAMESPACE
diff --git a/src/3rdparty/phonon/mmf/audioequalizer.h b/src/3rdparty/phonon/mmf/audioequalizer.h
index d4c8165..9c3770a 100644
--- a/src/3rdparty/phonon/mmf/audioequalizer.h
+++ b/src/3rdparty/phonon/mmf/audioequalizer.h
@@ -19,9 +19,10 @@ along with this library. If not, see <http://www.gnu.org/licenses/>.
#ifndef PHONON_MMF_AUDIOEQUALIZER_H
#define PHONON_MMF_AUDIOEQUALIZER_H
-#include <AudioEqualizerBase.h>
#include "abstractaudioeffect.h"
+class CAudioEqualizer;
+
QT_BEGIN_NAMESPACE
namespace Phonon
@@ -40,17 +41,22 @@ class AudioEqualizer : public AbstractAudioEffect
{
Q_OBJECT
public:
- AudioEqualizer(QObject *parent);
+ AudioEqualizer(QObject *parent, const QList<EffectParameter> &parameters);
-protected:
- virtual void parameterChanged(const int id,
- const QVariant &value);
+ // Static interface required by EffectFactory
+ static const char* description();
+ static bool getParameters(CMdaAudioOutputStream *stream,
+ QList<EffectParameter>& parameters);
- virtual bool activateOn(CPlayerType *player);
+protected:
+ // AbstractAudioEffect
+ virtual void createEffect(AudioPlayer::NativePlayer *player);
+ virtual int effectParameterChanged(const EffectParameter &param,
+ const QVariant &value);
private:
- static QList<EffectParameter> createParams();
- QScopedPointer<CAudioEqualizer> m_bassBoost;
+ CAudioEqualizer *concreteEffect();
+
};
}
}
diff --git a/src/3rdparty/phonon/mmf/audiooutput.cpp b/src/3rdparty/phonon/mmf/audiooutput.cpp
index d6e0c13..c6be20b 100644
--- a/src/3rdparty/phonon/mmf/audiooutput.cpp
+++ b/src/3rdparty/phonon/mmf/audiooutput.cpp
@@ -81,13 +81,18 @@ bool MMF::AudioOutput::setOutputDevice(int index)
return true;
}
-bool MMF::AudioOutput::activateOnMediaObject(MediaObject *mo)
+void MMF::AudioOutput::connectMediaObject(MediaObject *mediaObject)
{
// Ensure that the MediaObject has the correct initial volume
- mo->volumeChanged(m_volume);
+ mediaObject->volumeChanged(m_volume);
// Connect MediaObject to receive future volume changes
- connect(this, SIGNAL(volumeChanged(qreal)), mo, SLOT(volumeChanged(qreal)));
- return true;
+ connect(this, SIGNAL(volumeChanged(qreal)), mediaObject, SLOT(volumeChanged(qreal)));
+}
+
+void MMF::AudioOutput::disconnectMediaObject(MediaObject *mediaObject)
+{
+ // Disconnect all signal-slot connections
+ disconnect(this, 0, mediaObject, 0);
}
QHash<QByteArray, QVariant> MMF::AudioOutput::audioOutputDescription(int index)
diff --git a/src/3rdparty/phonon/mmf/audiooutput.h b/src/3rdparty/phonon/mmf/audiooutput.h
index 1e1e134..67aaa38 100644
--- a/src/3rdparty/phonon/mmf/audiooutput.h
+++ b/src/3rdparty/phonon/mmf/audiooutput.h
@@ -74,7 +74,9 @@ public:
};
protected:
- virtual bool activateOnMediaObject(MediaObject *mo);
+ // MediaNode
+ void connectMediaObject(MediaObject *mediaObject);
+ void disconnectMediaObject(MediaObject *mediaObject);
Q_SIGNALS:
void volumeChanged(qreal volume);
diff --git a/src/3rdparty/phonon/mmf/audioplayer.cpp b/src/3rdparty/phonon/mmf/audioplayer.cpp
index 8fccfe6..ee07229 100644
--- a/src/3rdparty/phonon/mmf/audioplayer.cpp
+++ b/src/3rdparty/phonon/mmf/audioplayer.cpp
@@ -34,13 +34,9 @@ using namespace Phonon::MMF;
// Constructor / destructor
//-----------------------------------------------------------------------------
-MMF::AudioPlayer::AudioPlayer()
-{
- construct();
-}
-
-MMF::AudioPlayer::AudioPlayer(const AbstractPlayer& player)
- : AbstractMediaPlayer(player)
+MMF::AudioPlayer::AudioPlayer(MediaObject *parent, const AbstractPlayer *player)
+ : AbstractMediaPlayer(parent, player)
+ , m_totalTime(0)
{
construct();
}
@@ -50,10 +46,10 @@ void MMF::AudioPlayer::construct()
TRACE_CONTEXT(AudioPlayer::AudioPlayer, EAudioApi);
TRACE_ENTRY_0();
- TRAPD(err, m_player.reset(CPlayerType::NewL(*this, 0, EMdaPriorityPreferenceNone)));
- if (KErrNone != err) {
- changeState(ErrorState);
- }
+ NativePlayer *player = 0;
+ QT_TRAP_THROWING(player = NativePlayer::NewL(*this, 0, EMdaPriorityPreferenceNone));
+ m_player.reset(player);
+ m_player->RegisterForAudioLoadingNotification(*this);
TRACE_EXIT_0();
}
@@ -66,6 +62,11 @@ MMF::AudioPlayer::~AudioPlayer()
TRACE_EXIT_0();
}
+MMF::AudioPlayer::NativePlayer *MMF::AudioPlayer::nativePlayer() const
+{
+ return m_player.data();
+}
+
//-----------------------------------------------------------------------------
// Public API
//-----------------------------------------------------------------------------
@@ -125,6 +126,24 @@ int MMF::AudioPlayer::openFile(RFile& file)
return err;
}
+int MMF::AudioPlayer::openUrl(const QString& /*url*/)
+{
+ // Streaming playback is generally not supported by the implementation
+ // of the audio player API, so we use CVideoPlayerUtility for both
+ // audio and video streaming.
+ Utils::panic(AudioUtilityUrlNotSupported);
+
+ // Silence warning
+ return 0;
+}
+
+int MMF::AudioPlayer::bufferStatus() const
+{
+ int result = 0;
+ TRAP_IGNORE(m_player->GetAudioLoadingProgressL(result));
+ return result;
+}
+
void MMF::AudioPlayer::close()
{
m_player->Close();
@@ -151,7 +170,7 @@ qint64 MMF::AudioPlayer::currentTime() const
// If we don't cast away constness here, we simply have to ignore
// the error.
- const_cast<AudioPlayer*>(this)->setError(NormalError);
+ const_cast<AudioPlayer*>(this)->setError(tr("Getting position failed"), err);
}
return result;
@@ -159,7 +178,7 @@ qint64 MMF::AudioPlayer::currentTime() const
qint64 MMF::AudioPlayer::totalTime() const
{
- return toMilliSeconds(m_player->Duration());
+ return m_totalTime;
}
@@ -182,12 +201,12 @@ void MMF::AudioPlayer::MapcInitComplete(TInt aError,
if (KErrNone == aError) {
maxVolumeChanged(m_player->MaxVolume());
- emit totalTimeChanged(totalTime());
+ m_totalTime = toMilliSeconds(m_player->Duration());
+ emit totalTimeChanged(m_totalTime);
updateMetaData();
changeState(StoppedState);
} else {
- // TODO: set different error states according to value of aError?
- setError(NormalError);
+ setError(tr("Opening clip failed"), aError);
}
TRACE_EXIT_0();
@@ -202,53 +221,39 @@ void MMF::AudioPlayer::MapcPlayComplete(TInt aError)
TRACE_CONTEXT(AudioPlayer::MapcPlayComplete, EAudioInternal);
TRACE_ENTRY("state %d error %d", state(), aError);
- stopTickTimer();
+ // Call base class function which handles end of playback for both
+ // audio and video clips.
+ playbackComplete(aError);
- if (KErrNone == aError) {
- changeState(StoppedState);
- // TODO: move on to m_nextSource
- } else {
- // TODO: do something with aError?
- setError(NormalError);
- }
+ TRACE_EXIT_0();
+}
- /*
- if (aError == KErrNone) {
- if (m_nextSource.type() == MediaSource::Empty) {
- emit finished();
- } else {
- setSource(m_nextSource);
- m_nextSource = MediaSource();
- }
-
- changeState(StoppedState);
- }
- else {
- m_error = NormalError;
- changeState(ErrorState);
- }
- */
+#ifdef QT_PHONON_MMF_AUDIO_DRM
+void MMF::AudioPlayer::MaloLoadingStarted()
+{
- TRACE_EXIT_0();
}
-CPlayerType *MMF::AudioPlayer::player() const
+void MMF::AudioPlayer::MaloLoadingComplete()
{
- return m_player.data();
+
}
+#endif // QT_PHONON_MMF_AUDIO_DRM
-#ifdef QT_PHONON_MMF_AUDIO_DRM
+//-----------------------------------------------------------------------------
+// MAudioLoadingObserver callbacks
+//-----------------------------------------------------------------------------
+
void MMF::AudioPlayer::MaloLoadingStarted()
{
-
+ bufferingStarted();
}
void MMF::AudioPlayer::MaloLoadingComplete()
{
-
+ bufferingComplete();
}
-#endif // QT_PHONON_MMF_AUDIO_DRM
//-----------------------------------------------------------------------------
diff --git a/src/3rdparty/phonon/mmf/audioplayer.h b/src/3rdparty/phonon/mmf/audioplayer.h
index bc60076..0eb8bb7 100644
--- a/src/3rdparty/phonon/mmf/audioplayer.h
+++ b/src/3rdparty/phonon/mmf/audioplayer.h
@@ -26,12 +26,10 @@ class TTimeIntervalMicroSeconds;
#ifdef QT_PHONON_MMF_AUDIO_DRM
#include <drmaudiosampleplayer.h>
-typedef CDrmPlayerUtility CPlayerType;
-typedef MDrmAudioPlayerCallback MPlayerObserverType;
+typedef MDrmAudioPlayerCallback NativePlayerObserver;
#else
#include <mdaaudiosampleplayer.h>
-typedef CMdaAudioPlayerUtility CPlayerType;
-typedef MMdaAudioPlayerCallback MPlayerObserverType;
+typedef MMdaAudioPlayerCallback NativePlayerObserver;
#endif
QT_BEGIN_NAMESPACE
@@ -44,18 +42,23 @@ namespace MMF
* @short Wrapper over MMF audio client utility
*/
class AudioPlayer : public AbstractMediaPlayer
- , public MPlayerObserverType // typedef
-#ifdef QT_PHONON_MMF_AUDIO_DRM
+ , public NativePlayerObserver
, public MAudioLoadingObserver
-#endif
{
Q_OBJECT
public:
- AudioPlayer();
- explicit AudioPlayer(const AbstractPlayer& player);
+ AudioPlayer(MediaObject *parent = 0, const AbstractPlayer *player = 0);
virtual ~AudioPlayer();
+#ifdef QT_PHONON_MMF_AUDIO_DRM
+typedef CDrmPlayerUtility NativePlayer;
+#else
+typedef CMdaAudioPlayerUtility NativePlayer;
+#endif
+
+ NativePlayer *nativePlayer() const;
+
// AbstractMediaPlayer
virtual void doPlay();
virtual void doPause();
@@ -63,6 +66,8 @@ public:
virtual void doSeek(qint64 milliseconds);
virtual int setDeviceVolume(int mmfVolume);
virtual int openFile(RFile& file);
+ virtual int openUrl(const QString& url);
+ virtual int bufferStatus() const;
virtual void close();
// MediaObjectInterface
@@ -70,15 +75,24 @@ public:
virtual qint64 currentTime() const;
virtual qint64 totalTime() const;
+ // AbstractMediaPlayer
+ virtual int numberOfMetaDataEntries() const;
+ virtual QPair<QString, QString> metaDataEntry(int index) const;
+
+ /**
+ * This class owns the pointer.
+ */
+ NativePlayer *player() const;
+
+private:
+ void construct();
+
+private:
#ifdef QT_PHONON_MMF_AUDIO_DRM
// MDrmAudioPlayerCallback
virtual void MdapcInitComplete(TInt aError,
const TTimeIntervalMicroSeconds &aDuration);
virtual void MdapcPlayComplete(TInt aError);
-
- // MAudioLoadingObserver
- virtual void MaloLoadingStarted();
- virtual void MaloLoadingComplete();
#else
// MMdaAudioPlayerCallback
virtual void MapcInitComplete(TInt aError,
@@ -86,24 +100,19 @@ public:
virtual void MapcPlayComplete(TInt aError);
#endif
- /**
- * This class owns the pointer.
- */
- CPlayerType *player() const;
-
-private:
- void construct();
-
- // AbstractMediaPlayer
- virtual int numberOfMetaDataEntries() const;
- virtual QPair<QString, QString> metaDataEntry(int index) const;
+ // MAudioLoadingObserver
+ virtual void MaloLoadingStarted();
+ virtual void MaloLoadingComplete();
private:
/**
* Using CPlayerType typedef in order to be able to easily switch between
* CMdaAudioPlayerUtility and CDrmPlayerUtility
*/
- QScopedPointer<CPlayerType> m_player;
+ QScopedPointer<NativePlayer> m_player;
+
+ qint64 m_totalTime;
+
};
}
}
diff --git a/src/3rdparty/phonon/mmf/backend.cpp b/src/3rdparty/phonon/mmf/backend.cpp
index 7e3a67f..3568a49 100644
--- a/src/3rdparty/phonon/mmf/backend.cpp
+++ b/src/3rdparty/phonon/mmf/backend.cpp
@@ -45,6 +45,7 @@ using namespace Phonon::MMF;
Backend::Backend(QObject *parent)
: QObject(parent)
, m_ancestorMoveMonitor(new AncestorMoveMonitor(this))
+ , m_effectFactory(new EffectFactory(this))
{
TRACE_CONTEXT(Backend::Backend, EBackend);
TRACE_ENTRY_0();
@@ -81,9 +82,9 @@ QObject *Backend::createObject(BackendInterface::Class c, QObject *parent, const
{
Q_ASSERT(args.count() == 1);
Q_ASSERT(args.first().type() == QVariant::Int);
- const AbstractAudioEffect::Type effect = AbstractAudioEffect::Type(args.first().toInt());
-
- return EffectFactory::createAudioEffect(effect, parent);
+ const EffectFactory::Type type =
+ static_cast<EffectFactory::Type>(args.first().toInt());
+ return m_effectFactory->createAudioEffect(type, parent);
}
case VideoWidgetClass:
result = new VideoWidget(m_ancestorMoveMonitor.data(), qobject_cast<QWidget *>(parent));
@@ -105,7 +106,7 @@ QList<int> Backend::objectDescriptionIndexes(ObjectDescriptionType type) const
switch(type)
{
case EffectType:
- retval.append(EffectFactory::effectIndexes());
+ retval.append(m_effectFactory->effectIndexes());
break;
case AudioOutputDeviceType:
// We only have one possible output device, but we need at least
@@ -126,7 +127,7 @@ QHash<QByteArray, QVariant> Backend::objectDescriptionProperties(ObjectDescripti
switch (type) {
case EffectType:
- return EffectFactory::audioEffectDescriptions(AbstractAudioEffect::Type(index));
+ return m_effectFactory->audioEffectDescriptions(EffectFactory::Type(index));
case AudioOutputDeviceType:
return AudioOutput::audioOutputDescription(index);
default:
@@ -139,29 +140,32 @@ bool Backend::startConnectionChange(QSet<QObject *>)
return true;
}
-bool Backend::connectNodes(QObject *source, QObject *target)
+bool Backend::connectNodes(QObject *sourceObject, QObject *targetObject)
{
TRACE_CONTEXT(Backend::connectNodes, EBackend);
- TRACE_ENTRY("source 0x%08x target 0x%08x", source, target);
- Q_ASSERT(qobject_cast<MediaNode *>(source));
- Q_ASSERT(qobject_cast<MediaNode *>(target));
+ TRACE_ENTRY("source 0x%08x target 0x%08x", sourceObject, targetObject);
+
+ MediaNode *const source = qobject_cast<MediaNode *>(sourceObject);
+ MediaNode *const target = qobject_cast<MediaNode *>(targetObject);
- MediaNode *const mediaSource = static_cast<MediaNode *>(source);
- MediaNode *const mediaTarget = static_cast<MediaNode *>(target);
+ Q_ASSERT_X(source, Q_FUNC_INFO, "source is not a MediaNode");
+ Q_ASSERT_X(target, Q_FUNC_INFO, "target is not a MediaNode");
- return mediaSource->connectMediaNode(mediaTarget);
+ return source->connectOutput(target);
}
-bool Backend::disconnectNodes(QObject *source, QObject *target)
+bool Backend::disconnectNodes(QObject *sourceObject, QObject *targetObject)
{
TRACE_CONTEXT(Backend::disconnectNodes, EBackend);
- TRACE_ENTRY("source 0x%08x target 0x%08x", source, target);
- Q_ASSERT(qobject_cast<MediaNode *>(source));
- Q_ASSERT(qobject_cast<MediaNode *>(target));
+ TRACE_ENTRY("source 0x%08x target 0x%08x", sourceObject, targetObject);
+
+ MediaNode *const source = qobject_cast<MediaNode *>(sourceObject);
+ MediaNode *const target = qobject_cast<MediaNode *>(targetObject);
- const bool result = static_cast<MediaNode *>(source)->disconnectMediaNode(static_cast<MediaNode *>(target));
+ Q_ASSERT_X(source, Q_FUNC_INFO, "source is not a MediaNode");
+ Q_ASSERT_X(target, Q_FUNC_INFO, "target is not a MediaNode");
- TRACE_RETURN("%d", result);
+ return source->disconnectOutput(target);
}
bool Backend::endConnectionChange(QSet<QObject *>)
diff --git a/src/3rdparty/phonon/mmf/backend.h b/src/3rdparty/phonon/mmf/backend.h
index 9e3d3b3..9361544 100644
--- a/src/3rdparty/phonon/mmf/backend.h
+++ b/src/3rdparty/phonon/mmf/backend.h
@@ -20,9 +20,10 @@ along with this library. If not, see <http://www.gnu.org/licenses/>.
#define PHONON_MMF_BACKEND_H
#include "ancestormovemonitor.h"
+#include "effectfactory.h"
-#include <Phonon/MediaSource>
-#include <Phonon/BackendInterface>
+#include <phonon/mediasource.h>
+#include <phonon/backendinterface.h>
#include <QScopedPointer>
QT_BEGIN_NAMESPACE
@@ -53,6 +54,7 @@ Q_SIGNALS:
private:
QScopedPointer<AncestorMoveMonitor> m_ancestorMoveMonitor;
+ QScopedPointer<EffectFactory> m_effectFactory;
};
}
diff --git a/src/3rdparty/phonon/mmf/bassboost.cpp b/src/3rdparty/phonon/mmf/bassboost.cpp
index e34f9e7..c7af939 100644
--- a/src/3rdparty/phonon/mmf/bassboost.cpp
+++ b/src/3rdparty/phonon/mmf/bassboost.cpp
@@ -16,6 +16,7 @@ along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <BassBoostBase.h>
#include "bassboost.h"
QT_BEGIN_NAMESPACE
@@ -23,25 +24,34 @@ QT_BEGIN_NAMESPACE
using namespace Phonon;
using namespace Phonon::MMF;
+// Define functions which depend on concrete native effect class name
+PHONON_MMF_DEFINE_EFFECT_FUNCTIONS(BassBoost)
+
/*! \class MMF::BassBoost
\internal
*/
-BassBoost::BassBoost(QObject *parent) : AbstractAudioEffect::AbstractAudioEffect(parent,
- QList<EffectParameter>())
+BassBoost::BassBoost(QObject *parent, const QList<EffectParameter> &parameters)
+ : AbstractAudioEffect::AbstractAudioEffect(parent, parameters)
{
+
}
-void BassBoost::parameterChanged(const int,
- const QVariant &)
+//-----------------------------------------------------------------------------
+// Static functions
+//-----------------------------------------------------------------------------
+
+const char* BassBoost::description()
{
- // We should never be called, because we have no parameters.
+ return "Bass boost";
}
-bool BassBoost::activateOn(CPlayerType *player)
+bool BassBoost::getParameters(CMdaAudioOutputStream *stream,
+ QList<EffectParameter> &parameters)
{
- m_effect.reset(CBassBoost::NewL(*player, true));
- return true;
+ QScopedPointer<CBassBoost> effect;
+ TRAPD(err, effect.reset(CBassBoost::NewL(*stream)));
+ return (KErrNone == err);
}
QT_END_NAMESPACE
diff --git a/src/3rdparty/phonon/mmf/bassboost.h b/src/3rdparty/phonon/mmf/bassboost.h
index c16393a..fc40e21 100644
--- a/src/3rdparty/phonon/mmf/bassboost.h
+++ b/src/3rdparty/phonon/mmf/bassboost.h
@@ -19,9 +19,10 @@ along with this library. If not, see <http://www.gnu.org/licenses/>.
#ifndef PHONON_MMF_BASSBOOST_H
#define PHONON_MMF_BASSBOOST_H
-#include <BassBoostBase.h>
#include "abstractaudioeffect.h"
+class CBassBoost;
+
QT_BEGIN_NAMESPACE
namespace Phonon
@@ -29,25 +30,26 @@ namespace Phonon
namespace MMF
{
/**
- * @short An "bass boost" effect.
- *
- * The documentation does not say what "bass boost" is, neither has it anykind
- * of setting. It's an on or off thing.
+ * @short A "bass boost" effect.
*/
class BassBoost : public AbstractAudioEffect
{
Q_OBJECT
public:
- BassBoost(QObject *parent);
+ BassBoost(QObject *parent, const QList<EffectParameter> &parameters);
-protected:
- virtual void parameterChanged(const int id,
- const QVariant &value);
+ // Static interface required by EffectFactory
+ static const char* description();
+ static bool getParameters(CMdaAudioOutputStream *stream,
+ QList<EffectParameter>& parameters);
- virtual bool activateOn(CPlayerType *player);
+protected:
+ // AbstractAudioEffect
+ virtual void createEffect(AudioPlayer::NativePlayer *player);
private:
- QScopedPointer<CBassBoost> m_bassBoost;
+ CBassBoost *concreteEffect();
+
};
}
}
diff --git a/src/3rdparty/phonon/mmf/dummyplayer.cpp b/src/3rdparty/phonon/mmf/dummyplayer.cpp
index e6f3855..6970088 100644
--- a/src/3rdparty/phonon/mmf/dummyplayer.cpp
+++ b/src/3rdparty/phonon/mmf/dummyplayer.cpp
@@ -31,12 +31,7 @@ using namespace Phonon::MMF;
// Constructor / destructor
//-----------------------------------------------------------------------------
-MMF::DummyPlayer::DummyPlayer()
-{
-
-}
-
-MMF::DummyPlayer::DummyPlayer(const AbstractPlayer& player)
+MMF::DummyPlayer::DummyPlayer(const AbstractPlayer *player)
: AbstractPlayer(player)
{
@@ -97,17 +92,7 @@ qint64 MMF::DummyPlayer::totalTime() const
return 0;
}
-MediaSource MMF::DummyPlayer::source() const
-{
- return MediaSource();
-}
-
-void MMF::DummyPlayer::setFileSource(const Phonon::MediaSource &, RFile &)
-{
-
-}
-
-void MMF::DummyPlayer::setNextSource(const MediaSource &)
+void MMF::DummyPlayer::open(const Phonon::MediaSource &, RFile &)
{
}
diff --git a/src/3rdparty/phonon/mmf/dummyplayer.h b/src/3rdparty/phonon/mmf/dummyplayer.h
index c6270c9..6841b5d 100644
--- a/src/3rdparty/phonon/mmf/dummyplayer.h
+++ b/src/3rdparty/phonon/mmf/dummyplayer.h
@@ -42,8 +42,7 @@ class AudioOutput;
class DummyPlayer : public AbstractPlayer
{
public:
- DummyPlayer();
- DummyPlayer(const AbstractPlayer& player);
+ DummyPlayer(const AbstractPlayer *player = 0);
// MediaObjectInterface
virtual void play();
@@ -56,12 +55,9 @@ public:
virtual Phonon::State state() const;
virtual Phonon::ErrorType errorType() const;
virtual qint64 totalTime() const;
- virtual MediaSource source() const;
- // virtual void setSource(const MediaSource &);
- virtual void setFileSource(const Phonon::MediaSource&, RFile&);
- virtual void setNextSource(const MediaSource &source);
// AbstractPlayer
+ virtual void open(const Phonon::MediaSource&, RFile&);
virtual void doSetTickInterval(qint32 interval);
};
}
diff --git a/src/3rdparty/phonon/mmf/effectfactory.cpp b/src/3rdparty/phonon/mmf/effectfactory.cpp
index e9c5e27..c5e33d5 100644
--- a/src/3rdparty/phonon/mmf/effectfactory.cpp
+++ b/src/3rdparty/phonon/mmf/effectfactory.cpp
@@ -19,19 +19,13 @@ along with this library. If not, see <http://www.gnu.org/licenses/>.
#include <QObject>
#include <QCoreApplication>
-#include <AudioEqualizerBase.h>
-#include <BassBoostBase.h>
-#include <DistanceAttenuationBase.h>
-#include <DopplerBase.h>
-#include <EnvironmentalReverbBase.h>
-#include <ListenerOrientationBase.h>
-#include <LocationBase.h>
-#include <LoudnessBase.h>
-#include <SourceOrientationBase.h>
-#include <StereoWideningBase.h>
+#include <mdaaudiooutputstream.h>
#include "audioequalizer.h"
#include "bassboost.h"
+#include "environmentalreverb.h"
+#include "loudness.h"
+#include "stereowidening.h"
#include "effectfactory.h"
@@ -44,111 +38,176 @@ using namespace Phonon::MMF;
\internal
*/
-QHash<QByteArray, QVariant> EffectFactory::constructEffectDescription(const QString &name,
- const QString &description)
+EffectFactory::EffectFactory(QObject *parent)
+ : QObject(parent)
+ , m_initialized(false)
{
- QHash<QByteArray, QVariant> retval;
- retval.insert("name", name);
- retval.insert("description", description);
- retval.insert("available", true);
-
- return retval;
}
-
-QHash<QByteArray, QVariant> EffectFactory::audioEffectDescriptions(AbstractAudioEffect::Type type)
+EffectFactory::~EffectFactory()
{
- switch (type)
- {
- case AbstractAudioEffect::EffectAudioEqualizer:
- return constructEffectDescription(QCoreApplication::translate("Phonon::MMF::EffectFactory", "Audio Equalizer"), "Audio equalizer.");
- case AbstractAudioEffect::EffectBassBoost:
- return constructEffectDescription(QCoreApplication::translate("Phonon::MMF::EffectFactory", "Bass Boost"), "Bass boost.");
- case AbstractAudioEffect::EffectDistanceAttenuation:
- return constructEffectDescription(QCoreApplication::translate("Phonon::MMF::EffectFactory", "Distance Attenuation"), "Distance Attenuation.");
- case AbstractAudioEffect::EffectEnvironmentalReverb:
- return constructEffectDescription(QCoreApplication::translate("Phonon::MMF::EffectFactory", "Environmental Reverb"), "Environmental Reverb.");
- case AbstractAudioEffect::EffectListenerOrientation:
- return constructEffectDescription(QCoreApplication::translate("Phonon::MMF::EffectFactory", "Environmental Reverb"), "Environmental Reverb.");
- case AbstractAudioEffect::EffectLoudness:
- return constructEffectDescription(QCoreApplication::translate("Phonon::MMF::EffectFactory", "Loudness"), "Loudness.");
- case AbstractAudioEffect::EffectSourceOrientation:
- return constructEffectDescription(QCoreApplication::translate("Phonon::MMF::EffectFactory", "Source Orientation"), "Source Orientation.");
- case AbstractAudioEffect::EffectStereoWidening:
- return constructEffectDescription(QCoreApplication::translate("Phonon::MMF::EffectFactory", "Stereo Widening"), "Stereo Widening.");
- }
- Q_ASSERT_X(false, Q_FUNC_INFO, "Unknown effect type.");
- return QHash<QByteArray, QVariant>();
}
-AbstractAudioEffect *EffectFactory::createAudioEffect(AbstractAudioEffect::Type type,
+//-----------------------------------------------------------------------------
+// Public functions
+//-----------------------------------------------------------------------------
+
+AbstractAudioEffect *EffectFactory::createAudioEffect(Type type,
QObject *parent)
{
+ // Lazily initialize
+ if (!m_initialized)
+ initialize();
+
Q_ASSERT(parent);
+ const QList<EffectParameter>& parameters = data(type).m_parameters;
+
+ AbstractAudioEffect *effect = 0;
+
switch (type)
{
- case AbstractAudioEffect::EffectBassBoost:
- return new BassBoost(parent);
- case AbstractAudioEffect::EffectAudioEqualizer:
- return new AudioEqualizer(parent);
- case AbstractAudioEffect::EffectDistanceAttenuation:
- case AbstractAudioEffect::EffectEnvironmentalReverb:
- case AbstractAudioEffect::EffectListenerOrientation:
- case AbstractAudioEffect::EffectLoudness:
- case AbstractAudioEffect::EffectSourceOrientation:
- case AbstractAudioEffect::EffectStereoWidening:
- ;
+ case TypeBassBoost:
+ effect = new BassBoost(parent, parameters);
+ break;
+ case TypeAudioEqualizer:
+ effect = new AudioEqualizer(parent, parameters);
+ break;
+ case TypeEnvironmentalReverb:
+ effect = new EnvironmentalReverb(parent, parameters);
+ break;
+ case TypeLoudness:
+ effect = new Loudness(parent, parameters);
+ break;
+ case TypeStereoWidening:
+ effect = new StereoWidening(parent, parameters);
+ break;
+
+ // Not implemented
+ case TypeDistanceAttenuation:
+ case TypeListenerOrientation:
+ case TypeSourceOrientation:
+ // Fall through
+ default:
+ Q_ASSERT_X(false, Q_FUNC_INFO, "Unknown effect");
}
- Q_ASSERT_X(false, Q_FUNC_INFO, "Unknown effect.");
- return 0;
+ return effect;
}
-template<typename TEffect>
-bool isEffectSupported()
+QHash<QByteArray, QVariant> EffectFactory::audioEffectDescriptions(Type type)
{
- AudioPlayer audioPlayer;
-
- QScopedPointer<TEffect> eff;
- TRAPD(errorCode, eff.reset(TEffect::NewL(*audioPlayer.player())));
+ // Lazily initialize
+ if (!m_initialized)
+ initialize();
- return errorCode != KErrNone;
+ return data(type).m_descriptions;
}
QList<int> EffectFactory::effectIndexes()
{
- QList<int> retval;
+ // Lazily initialize
+ if (!m_initialized)
+ initialize();
- if (isEffectSupported<CAudioEqualizer>())
- retval.append(AbstractAudioEffect::EffectAudioEqualizer);
+ QList<int> result;
- if (isEffectSupported<CBassBoost>())
- retval.append(AbstractAudioEffect::EffectBassBoost);
+ QHash<Type, EffectData>::const_iterator i = m_effectData.begin();
+ for ( ; i != m_effectData.end(); ++i)
+ if (i.value().m_supported)
+ result.append(i.key());
- /* We haven't implemented these yet.
- if (isEffectSupported<CDistanceAttenuation>())
- retval.append(AbstractAudioEffect::EffectDistanceAttenuation);
+ return result;
+}
- if (isEffectSupported<CEnvironmentalReverb>())
- retval.append(AbstractAudioEffect::EffectEnvironmentalReverb);
+//-----------------------------------------------------------------------------
+// Private functions
+//-----------------------------------------------------------------------------
- if (isEffectSupported<CLoudness>())
- retval.append(AbstractAudioEffect::EffectLoudness);
+#define INITIALIZE_EFFECT(Effect) \
+ { \
+ EffectData data = getData<Effect>(); \
+ m_effectData.insert(Type##Effect, data); \
+ }
- if (isEffectSupported<CListenerOrientation>())
- retval.append(AbstractAudioEffect::EffectListenerOrientation);
+void EffectFactory::initialize()
+{
+ Q_ASSERT_X(!m_initialized, Q_FUNC_INFO, "Already initialized");
- if (isEffectSupported<CSourceOrientation>())
- retval.append(AbstractAudioEffect::EffectSourceOrientation);
+ INITIALIZE_EFFECT(AudioEqualizer)
+ INITIALIZE_EFFECT(BassBoost)
+ INITIALIZE_EFFECT(EnvironmentalReverb)
+ INITIALIZE_EFFECT(Loudness)
+ INITIALIZE_EFFECT(StereoWidening)
- if (isEffectSupported<CStereoWidening>())
- retval.append(AbstractAudioEffect::EffectStereoWidening);
- */
+ m_initialized = true;
+}
+
+// This class is just a wrapper which allows us to instantiate a
+// CMdaAudioOutputStream object. This is done in order to allow the
+// effects API to query the DevSound implementation, to discover
+// which effects are supported and what parameters they take.
+// Ideally, we would use CMMFDevSound directly, but this class is not
+// available in the public S60 SDK.
+class OutputStreamFactory : public MMdaAudioOutputStreamCallback
+{
+public:
+ CMdaAudioOutputStream* create()
+ {
+ CMdaAudioOutputStream* stream = 0;
+ QT_TRAP_THROWING(stream = CMdaAudioOutputStream::NewL(*this));
+ return stream;
+ }
+private:
+ void MaoscOpenComplete(TInt /*aError*/) { }
+ void MaoscBufferCopied(TInt /*aError*/, const TDesC8& /*aBuffer*/) { }
+ void MaoscPlayComplete(TInt /*aError*/) { }
+};
+
+template<typename BackendNode>
+EffectFactory::EffectData EffectFactory::getData()
+{
+ EffectData data;
+
+ // Create a temporary CMdaAudioOutputStream object, so that the effects
+ // API can query DevSound to discover which effects are supported.
+ OutputStreamFactory streamFactory;
+ QScopedPointer<CMdaAudioOutputStream> stream(streamFactory.create());
+
+ EffectParameter param(
+ /* parameterId */ AbstractAudioEffect::ParameterEnable,
+ /* name */ tr("Enabled"),
+ /* hints */ EffectParameter::ToggledHint,
+ /* defaultValue */ QVariant(bool(true)));
+ data.m_parameters.append(param);
+
+ if (data.m_supported = BackendNode::getParameters
+ (stream.data(), data.m_parameters)) {
+ const QString description = QCoreApplication::translate
+ ("Phonon::MMF::EffectFactory", BackendNode::description());
+ data.m_descriptions.insert("name", description);
+ data.m_descriptions.insert("description", description);
+ data.m_descriptions.insert("available", true);
+ }
+
+ // Sanity check to ensure that all parameter IDs are unique
+ QSet<int> ids;
+ foreach (param, data.m_parameters) {
+ Q_ASSERT_X(ids.find(param.id()) == ids.end(), Q_FUNC_INFO,
+ "Parameter list contains duplicates");
+ ids.insert(param.id());
+ }
- return retval;
+ return data;
+}
+
+const EffectFactory::EffectData& EffectFactory::data(Type type) const
+{
+ QHash<Type, EffectData>::const_iterator i = m_effectData.find(type);
+ Q_ASSERT_X(i != m_effectData.end(), Q_FUNC_INFO, "Effect data not found");
+ return i.value();
}
QT_END_NAMESPACE
diff --git a/src/3rdparty/phonon/mmf/effectfactory.h b/src/3rdparty/phonon/mmf/effectfactory.h
index e83ad15..dd4b58d 100644
--- a/src/3rdparty/phonon/mmf/effectfactory.h
+++ b/src/3rdparty/phonon/mmf/effectfactory.h
@@ -20,6 +20,7 @@ along with this library. If not, see <http://www.gnu.org/licenses/>.
#define PHONON_MMF_EFFECTFACTORY_H
#include "abstractaudioeffect.h"
+#include "effectparameter.h"
QT_BEGIN_NAMESPACE
@@ -31,14 +32,30 @@ namespace MMF
/**
* @short Contains utility functions related to effects.
*/
-class EffectFactory
+class EffectFactory : public QObject
{
+ Q_OBJECT
+
public:
+ EffectFactory(QObject *parent);
+ ~EffectFactory();
+
+ enum Type
+ {
+ TypeAudioEqualizer = 0
+ , TypeBassBoost
+ , TypeDistanceAttenuation
+ , TypeEnvironmentalReverb
+ , TypeListenerOrientation
+ , TypeLoudness
+ , TypeSourceOrientation
+ , TypeStereoWidening
+ };
+
/**
* @short Creates an audio effect of type @p type.
*/
- static AbstractAudioEffect *createAudioEffect(AbstractAudioEffect::Type type,
- QObject *parent);
+ AbstractAudioEffect *createAudioEffect(Type type, QObject *parent);
/**
* @short Return the properties for effect @p type.
@@ -46,7 +63,7 @@ public:
* This handles the effects for
* BackendInterface::objectDescriptionProperties().
*/
- static QHash<QByteArray, QVariant> audioEffectDescriptions(AbstractAudioEffect::Type type);
+ QHash<QByteArray, QVariant> audioEffectDescriptions(Type type);
/**
* @short Returns the indexes for the supported effects.
@@ -54,19 +71,27 @@ public:
* This handles the effects for
* BackendInterface::objectDescriptionIndexes().
*/
- static QList<int> effectIndexes();
+ QList<int> effectIndexes();
private:
- static inline QHash<QByteArray, QVariant> constructEffectDescription(const QString &name,
- const QString &description);
+ void initialize();
+
+ struct EffectData
+ {
+ bool m_supported;
+ QHash<QByteArray, QVariant> m_descriptions;
+ QList<EffectParameter> m_parameters;
+ };
+
+ template<typename BackendNode> EffectData getData();
+ const EffectData& data(Type type) const;
+
+private:
+ bool m_initialized;
+ QHash<Type, EffectData> m_effectData;
- /**
- * This class is not supposed to be instantiated, so disable
- * the default constructor.
- */
- inline EffectFactory();
- Q_DISABLE_COPY(EffectFactory)
};
+
}
}
diff --git a/src/3rdparty/phonon/mmf/effectparameter.cpp b/src/3rdparty/phonon/mmf/effectparameter.cpp
new file mode 100644
index 0000000..17c1315
--- /dev/null
+++ b/src/3rdparty/phonon/mmf/effectparameter.cpp
@@ -0,0 +1,71 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library is free software: you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation, either version 2.1 or 3 of the License.
+
+This library 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 Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with this library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "effectparameter.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace Phonon;
+using namespace Phonon::MMF;
+
+/*! \class MMF::EffectParameter
+ \internal
+*/
+
+MMF::EffectParameter::EffectParameter()
+ : m_hasInternalRange(false)
+{
+
+}
+
+MMF::EffectParameter::EffectParameter(
+ int parameterId, const QString &name, Hints hints,
+ const QVariant &defaultValue, const QVariant &min,
+ const QVariant &max, const QVariantList &values,
+ const QString &description)
+ : Phonon::EffectParameter(parameterId, name, hints, defaultValue,
+ min, max, values, description)
+ , m_hasInternalRange(false)
+{
+
+}
+
+void MMF::EffectParameter::setInternalRange(qint32 min, qint32 max)
+{
+ Q_ASSERT_X(max >= min, Q_FUNC_INFO, "Invalid range");
+ m_internalRange = QPair<qint32, qint32>(min, max);
+ m_hasInternalRange = true;
+}
+
+qint32 MMF::EffectParameter::toInternalValue(qreal external) const
+{
+ Q_ASSERT_X(m_hasInternalRange, Q_FUNC_INFO, "Does not have internal range");
+ const qint32 range = m_internalRange.second - m_internalRange.first;
+ return m_internalRange.first + ((1.0 + external) / 2) * range;
+}
+
+qreal MMF::EffectParameter::toExternalValue
+ (qint32 value, qint32 min, qint32 max)
+{
+ Q_ASSERT_X(max >= min, Q_FUNC_INFO, "Invalid range");
+ const qint32 range = max - min;
+ return range == 0 ? 0.0 : ((2.0 * value - min) / range) - 1.0;
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/3rdparty/phonon/mmf/effectparameter.h b/src/3rdparty/phonon/mmf/effectparameter.h
new file mode 100644
index 0000000..892ed4d
--- /dev/null
+++ b/src/3rdparty/phonon/mmf/effectparameter.h
@@ -0,0 +1,74 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library is free software: you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation, either version 2.1 or 3 of the License.
+
+This library 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 Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with this library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef PHONON_MMF_EFFECTPARAMETER_H
+#define PHONON_MMF_EFFECTPARAMETER_H
+
+#include <phonon/effectparameter.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace MMF
+{
+
+/**
+ * @short Parameter value for an audio effect
+ *
+ * The base class is extended in order to work around a shortcoming
+ * in Phonon::EffectWidget. This widget only displays sliders for
+ * parameters with numeric values if the variant type of the parameter
+ * is QReal and the range is exactly -1.0 to +1.0; otherwise, a
+ * spinbox is used to set numeric parameters. This is rather
+ * inconvenient for many effects, such as the audio equalizer, for
+ * which a slider is a much more natural UI control.
+ *
+ * For many such parameters, we therefore report the type to be QReal
+ * and the range to be -1.0 to +1.0. This class stores the actual
+ * integer range for the parameter, and provides the toInternalValue
+ * function for converting between the client-side floating point
+ * value and the internal integer value.
+ */
+class EffectParameter : public Phonon::EffectParameter
+{
+public:
+ EffectParameter();
+ EffectParameter(int parameterId, const QString &name, Hints hints,
+ const QVariant &defaultValue, const QVariant &min = QVariant(),
+ const QVariant &max = QVariant(), const QVariantList &values = QVariantList(),
+ const QString &description = QString());
+
+ void setInternalRange(qint32 min, qint32 max);
+ qint32 toInternalValue(qreal external) const;
+
+ static qreal toExternalValue(qint32 value, qint32 min, qint32 max);
+
+private:
+ bool m_hasInternalRange;
+ QPair<qint32, qint32> m_internalRange;
+
+};
+
+}
+}
+
+QT_END_NAMESPACE
+
+#endif
+
diff --git a/src/3rdparty/phonon/mmf/environmentalreverb.cpp b/src/3rdparty/phonon/mmf/environmentalreverb.cpp
new file mode 100644
index 0000000..89f8d60
--- /dev/null
+++ b/src/3rdparty/phonon/mmf/environmentalreverb.cpp
@@ -0,0 +1,201 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library is free software: you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation, either version 2.1 or 3 of the License.
+
+This library 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 Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with this library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include <EnvironmentalReverbBase.h>
+#include "environmentalreverb.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace Phonon;
+using namespace Phonon::MMF;
+
+/*! \class MMF::EnvironmentalReverb
+ \internal
+*/
+
+// Define functions which depend on concrete native effect class name
+PHONON_MMF_DEFINE_EFFECT_FUNCTIONS(EnvironmentalReverb)
+
+enum Parameters
+{
+ DecayHFRatio = AbstractAudioEffect::ParameterBase,
+ DecayTime,
+ Density,
+ Diffusion,
+ ReflectionsDelay,
+ ReflectionsLevel,
+ ReverbDelay,
+ ReverbLevel,
+ RoomHFLevel,
+ RoomLevel
+};
+
+EnvironmentalReverb::EnvironmentalReverb(QObject *parent, const QList<EffectParameter>& parameters)
+ : AbstractAudioEffect::AbstractAudioEffect(parent, parameters)
+{
+
+}
+
+int EnvironmentalReverb::effectParameterChanged(const EffectParameter &param,
+ const QVariant &value)
+{
+ const qreal externalLevel = value.toReal();
+ const int internalLevel = param.toInternalValue(externalLevel);
+
+ TInt err = 0;
+
+ switch(param.id()) {
+ case DecayHFRatio:
+ TRAP(err, concreteEffect()->SetDecayHFRatioL(internalLevel));
+ break;
+ case DecayTime:
+ TRAP(err, concreteEffect()->SetDecayTimeL(internalLevel));
+ break;
+ case Density:
+ TRAP(err, concreteEffect()->SetDensityL(internalLevel));
+ break;
+ case Diffusion:
+ TRAP(err, concreteEffect()->SetDiffusionL(internalLevel));
+ break;
+ case ReflectionsDelay:
+ TRAP(err, concreteEffect()->SetReflectionsDelayL(internalLevel));
+ break;
+ case ReflectionsLevel:
+ TRAP(err, concreteEffect()->SetReflectionsLevelL(internalLevel));
+ break;
+ case ReverbDelay:
+ TRAP(err, concreteEffect()->SetReverbDelayL(internalLevel));
+ break;
+ case ReverbLevel:
+ TRAP(err, concreteEffect()->SetReverbLevelL(internalLevel));
+ break;
+ case RoomHFLevel:
+ TRAP(err, concreteEffect()->SetRoomHFLevelL(internalLevel));
+ break;
+ case RoomLevel:
+ TRAP(err, concreteEffect()->SetRoomLevelL(internalLevel));
+ break;
+ default:
+ Q_ASSERT_X(false, Q_FUNC_INFO, "Unknown parameter");
+ }
+
+ return err;
+}
+
+
+//-----------------------------------------------------------------------------
+// Static functions
+//-----------------------------------------------------------------------------
+
+const char* EnvironmentalReverb::description()
+{
+ return "Reverb";
+}
+
+// Internal helper function
+Phonon::MMF::EffectParameter createParameter(int id, const QString &name,
+ int defaultValue, int minValue, int maxValue,
+ Phonon::EffectParameter::Hint hint = Phonon::EffectParameter::IntegerHint)
+{
+ const qreal externalDefaultValue =
+ Phonon::MMF::EffectParameter::toExternalValue
+ (defaultValue, minValue, maxValue);
+
+ Phonon::MMF::EffectParameter param(id, name, hint,
+ /* defaultValue */ QVariant(externalDefaultValue),
+ /* minimumValue */ QVariant(qreal(-1.0)),
+ /* maximumValue */ QVariant(qreal(+1.0)));
+
+ param.setInternalRange(minValue, maxValue);
+ return param;
+}
+
+bool EnvironmentalReverb::getParameters(CMdaAudioOutputStream *stream,
+ QList<EffectParameter>& parameters)
+{
+ bool supported = false;
+
+ QScopedPointer<CEnvironmentalReverb> effect;
+ TRAPD(err, effect.reset(CEnvironmentalReverb::NewL(*stream)));
+
+ if (KErrNone == err) {
+ supported = true;
+
+ TInt32 min, max;
+ TUint32 umin, umax;
+
+ // DecayHFRatio
+ effect->DecayHFRatioRange(umin, umax);
+ parameters.append(createParameter(
+ DecayHFRatio, tr("Decay HF ratio (%)"), effect->DecayHFRatio(),
+ umin, umax));
+
+ // DecayTime
+ effect->DecayTimeRange(umin, umax);
+ parameters.append(createParameter(
+ DecayTime, tr("Decay time (ms)"), effect->DecayTime(),
+ umin, umax));
+
+ // Density
+ parameters.append(createParameter(
+ Density, tr("Density (%)"), effect->Density(), 0, 100));
+
+ // Diffusion
+ parameters.append(createParameter(
+ Diffusion, tr("Diffusion (%)"), effect->Diffusion(), 0, 100));
+
+ // ReflectionsDelay
+ parameters.append(createParameter(
+ ReflectionsDelay, tr("Reflections delay (ms)"),
+ effect->ReflectionsDelay(), 0, effect->ReflectionsDelayMax()));
+
+ // ReflectionsLevel
+ effect->ReflectionLevelRange(min, max);
+ parameters.append(createParameter(
+ ReflectionsLevel, tr("Reflections level (mB)"),
+ effect->ReflectionsLevel(),
+ min, max, EffectParameter::LogarithmicHint));
+
+ // ReverbDelay
+ parameters.append(createParameter(
+ ReverbDelay, tr("Reverb delay (ms)"), effect->ReverbDelay(),
+ 0, effect->ReverbDelayMax()));
+
+ // ReverbLevel
+ effect->ReverbLevelRange(min, max);
+ parameters.append(createParameter(
+ ReverbLevel, tr("Reverb level (mB)"), effect->ReverbLevel(),
+ min, max, EffectParameter::LogarithmicHint));
+
+ // RoomHFLevel
+ effect->RoomHFLevelRange(min, max);
+ parameters.append(createParameter(
+ RoomHFLevel, tr("Room HF level"), effect->RoomHFLevel(),
+ min, max));
+
+ // RoomLevel
+ effect->RoomLevelRange(min, max);
+ parameters.append(createParameter(
+ RoomLevel, tr("Room level (mB)"), effect->RoomLevel(),
+ min, max, EffectParameter::LogarithmicHint));
+ }
+
+ return supported;
+}
+
+QT_END_NAMESPACE
diff --git a/src/3rdparty/phonon/mmf/environmentalreverb.h b/src/3rdparty/phonon/mmf/environmentalreverb.h
new file mode 100644
index 0000000..eab68c6
--- /dev/null
+++ b/src/3rdparty/phonon/mmf/environmentalreverb.h
@@ -0,0 +1,62 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library is free software: you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation, either version 2.1 or 3 of the License.
+
+This library 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 Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with this library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef PHONON_MMF_ENVIRONMENTALREVERB_H
+#define PHONON_MMF_ENVIRONMENTALREVERB_H
+
+#include "abstractaudioeffect.h"
+
+class CEnvironmentalReverb;
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace MMF
+{
+/**
+ * @short A reverb effect.
+ */
+class EnvironmentalReverb : public AbstractAudioEffect
+{
+ Q_OBJECT
+public:
+ EnvironmentalReverb(QObject *parent, const QList<EffectParameter>& parameters);
+
+ // Static interface required by EffectFactory
+ static const char* description();
+ static bool getParameters(CMdaAudioOutputStream *stream,
+ QList<EffectParameter>& parameters);
+
+protected:
+ // AbstractAudioEffect
+ virtual void createEffect(AudioPlayer::NativePlayer *player);
+ virtual int effectParameterChanged(const EffectParameter &param,
+ const QVariant &value);
+
+private:
+ CEnvironmentalReverb *concreteEffect();
+
+};
+}
+}
+
+QT_END_NAMESPACE
+
+#endif
+
diff --git a/src/3rdparty/phonon/mmf/loudness.cpp b/src/3rdparty/phonon/mmf/loudness.cpp
new file mode 100644
index 0000000..1079a35
--- /dev/null
+++ b/src/3rdparty/phonon/mmf/loudness.cpp
@@ -0,0 +1,58 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library is free software: you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation, either version 2.1 or 3 of the License.
+
+This library 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 Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with this library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include <LoudnessBase.h>
+#include "loudness.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace Phonon;
+using namespace Phonon::MMF;
+
+// Define functions which depend on concrete native effect class name
+PHONON_MMF_DEFINE_EFFECT_FUNCTIONS(Loudness)
+
+/*! \class MMF::Loudness
+ \internal
+*/
+
+Loudness::Loudness(QObject *parent, const QList<EffectParameter>& parameters)
+ : AbstractAudioEffect::AbstractAudioEffect(parent, parameters)
+{
+
+}
+
+//-----------------------------------------------------------------------------
+// Static functions
+//-----------------------------------------------------------------------------
+
+const char* Loudness::description()
+{
+ return "Loudness";
+}
+
+bool Loudness::getParameters(CMdaAudioOutputStream *stream,
+ QList<EffectParameter> &parameters)
+{
+ QScopedPointer<CLoudness> effect;
+ TRAPD(err, effect.reset(CLoudness::NewL(*stream)));
+ return (KErrNone == err);
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/3rdparty/phonon/mmf/loudness.h b/src/3rdparty/phonon/mmf/loudness.h
new file mode 100644
index 0000000..a688a67
--- /dev/null
+++ b/src/3rdparty/phonon/mmf/loudness.h
@@ -0,0 +1,60 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library is free software: you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation, either version 2.1 or 3 of the License.
+
+This library 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 Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with this library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef PHONON_MMF_LOUDNESS_H
+#define PHONON_MMF_LOUDNESS_H
+
+#include "abstractaudioeffect.h"
+
+class CLoudness;
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace MMF
+{
+/**
+ * @short A "loudness" effect.
+ */
+class Loudness : public AbstractAudioEffect
+{
+ Q_OBJECT
+public:
+ Loudness(QObject *parent, const QList<EffectParameter>& parameters);
+
+ // Static interface required by EffectFactory
+ static const char* description();
+ static bool getParameters(CMdaAudioOutputStream *stream,
+ QList<EffectParameter>& parameters);
+
+protected:
+ // AbstractAudioEffect
+ virtual void createEffect(AudioPlayer::NativePlayer *player);
+
+private:
+ CLoudness *concreteEffect();
+
+};
+}
+}
+
+QT_END_NAMESPACE
+
+#endif
+
diff --git a/src/3rdparty/phonon/mmf/mediaobject.cpp b/src/3rdparty/phonon/mmf/mediaobject.cpp
index 21dcfe1..9744774 100644
--- a/src/3rdparty/phonon/mmf/mediaobject.cpp
+++ b/src/3rdparty/phonon/mmf/mediaobject.cpp
@@ -45,6 +45,7 @@ using namespace Phonon::MMF;
MMF::MediaObject::MediaObject(QObject *parent) : MMF::MediaNode::MediaNode(parent)
, m_recognizerOpened(false)
+ , m_nextSourceSet(false)
{
m_player.reset(new DummyPlayer());
@@ -211,18 +212,20 @@ qint64 MMF::MediaObject::totalTime() const
MediaSource MMF::MediaObject::source() const
{
- return m_player->source();
+ return m_source;
}
void MMF::MediaObject::setSource(const MediaSource &source)
{
- createPlayer(source);
-
- // This is a hack to work around KErrInUse from MMF client utility
- // OpenFileL calls
- m_player->setFileSource(source, m_file);
+ switchToSource(source);
+}
- emit currentSourceChanged(source);
+void MMF::MediaObject::switchToSource(const MediaSource &source)
+{
+ createPlayer(source);
+ m_source = source;
+ m_player->open(m_source, m_file);
+ emit currentSourceChanged(m_source);
}
void MMF::MediaObject::createPlayer(const MediaSource &source)
@@ -238,7 +241,6 @@ void MMF::MediaObject::createPlayer(const MediaSource &source)
const bool oldPlayerHasVideo = oldPlayer->hasVideo();
const bool oldPlayerSeekable = oldPlayer->isSeekable();
- Phonon::ErrorType error = NoError;
QString errorMessage;
// Determine media type
@@ -254,8 +256,10 @@ void MMF::MediaObject::createPlayer(const MediaSource &source)
mediaType = fileMediaType(url.toLocalFile());
}
else {
- errorMessage = QLatin1String("Network streaming not supported yet");
- error = NormalError;
+ // Streaming playback is generally not supported by the implementation
+ // of the audio player API, so we use CVideoPlayerUtility for both
+ // audio and video streaming.
+ mediaType = MediaTypeVideo;
}
}
break;
@@ -263,8 +267,7 @@ void MMF::MediaObject::createPlayer(const MediaSource &source)
case MediaSource::Invalid:
case MediaSource::Disc:
case MediaSource::Stream:
- TRACE_0("Unsupported media type");
- error = NormalError;
+ errorMessage = tr("Error opening source: type not supported");
break;
case MediaSource::Empty:
@@ -281,34 +284,23 @@ void MMF::MediaObject::createPlayer(const MediaSource &source)
switch (mediaType) {
case MediaTypeUnknown:
TRACE_0("Media type could not be determined");
- if (oldPlayer) {
- newPlayer = new DummyPlayer(*oldPlayer);
- } else {
- newPlayer = new DummyPlayer();
- }
-
- error = NormalError;
- errorMessage = tr("Media type could not be determined");
+ newPlayer = new DummyPlayer(oldPlayer);
+ errorMessage = tr("Error opening source: media type could not be determined");
break;
case MediaTypeAudio:
- if (oldPlayer) {
- newPlayer = new AudioPlayer(*oldPlayer);
- } else {
- newPlayer = new AudioPlayer();
- }
+ newPlayer = new AudioPlayer(this, oldPlayer);
break;
case MediaTypeVideo:
- if (oldPlayer) {
- newPlayer = new VideoPlayer(*oldPlayer);
- } else {
- newPlayer = new VideoPlayer();
- }
+ newPlayer = new VideoPlayer(this, oldPlayer);
break;
}
+ if (oldPlayer)
+ emit abstractPlayerChanged(0);
m_player.reset(newPlayer);
+ emit abstractPlayerChanged(newPlayer);
if (oldPlayerHasVideo != hasVideo()) {
emit hasVideoChanged(hasVideo());
@@ -322,13 +314,16 @@ void MMF::MediaObject::createPlayer(const MediaSource &source)
connect(m_player.data(), SIGNAL(stateChanged(Phonon::State,Phonon::State)), SIGNAL(stateChanged(Phonon::State,Phonon::State)));
connect(m_player.data(), SIGNAL(finished()), SIGNAL(finished()));
connect(m_player.data(), SIGNAL(tick(qint64)), SIGNAL(tick(qint64)));
+ connect(m_player.data(), SIGNAL(bufferStatus(int)), SIGNAL(bufferStatus(int)));
connect(m_player.data(), SIGNAL(metaDataChanged(QMultiMap<QString,QString>)), SIGNAL(metaDataChanged(QMultiMap<QString,QString>)));
+ connect(m_player.data(), SIGNAL(aboutToFinish()), SIGNAL(aboutToFinish()));
+ connect(m_player.data(), SIGNAL(prefinishMarkReached(qint32)), SIGNAL(tick(qint32)));
// We need to call setError() after doing the connects, otherwise the
// error won't be received.
- if (error != NoError) {
+ if (!errorMessage.isEmpty()) {
Q_ASSERT(m_player);
- m_player->setError(error, errorMessage);
+ m_player->setError(errorMessage);
}
TRACE_EXIT_0();
@@ -336,7 +331,8 @@ void MMF::MediaObject::createPlayer(const MediaSource &source)
void MMF::MediaObject::setNextSource(const MediaSource &source)
{
- m_player->setNextSource(source);
+ m_nextSource = source;
+ m_nextSourceSet = true;
}
qint32 MMF::MediaObject::prefinishMark() const
@@ -365,6 +361,25 @@ void MMF::MediaObject::volumeChanged(qreal volume)
}
//-----------------------------------------------------------------------------
+// MediaNode
+//-----------------------------------------------------------------------------
+
+void MMF::MediaObject::connectMediaObject(MediaObject * /*mediaObject*/)
+{
+ // This function should never be called - see MediaNode::setMediaObject()
+ Q_ASSERT_X(false, Q_FUNC_INFO,
+ "Connection of MediaObject to MediaObject");
+}
+
+void MMF::MediaObject::disconnectMediaObject(MediaObject * /*mediaObject*/)
+{
+ // This function should never be called - see MediaNode::setMediaObject()
+ Q_ASSERT_X(false, Q_FUNC_INFO,
+ "Disconnection of MediaObject from MediaObject");
+}
+
+
+//-----------------------------------------------------------------------------
// Video output
//-----------------------------------------------------------------------------
@@ -379,10 +394,17 @@ AbstractPlayer *MMF::MediaObject::abstractPlayer() const
return m_player.data();
}
-bool MMF::MediaObject::activateOnMediaObject(MediaObject *)
+//-----------------------------------------------------------------------------
+// Playlist support
+//-----------------------------------------------------------------------------
+
+void MMF::MediaObject::switchToNextSource()
{
- // Guess what, we do nothing.
- return true;
+ if (m_nextSourceSet) {
+ m_nextSourceSet = false;
+ switchToSource(m_nextSource);
+ play();
+ }
}
QT_END_NAMESPACE
diff --git a/src/3rdparty/phonon/mmf/mediaobject.h b/src/3rdparty/phonon/mmf/mediaobject.h
index ee94ea2..d6248e2 100644
--- a/src/3rdparty/phonon/mmf/mediaobject.h
+++ b/src/3rdparty/phonon/mmf/mediaobject.h
@@ -19,8 +19,8 @@ along with this library. If not, see <http://www.gnu.org/licenses/>.
#ifndef PHONON_MMF_MEDIAOBJECT_H
#define PHONON_MMF_MEDIAOBJECT_H
-#include <Phonon/MediaSource>
-#include <Phonon/MediaObjectInterface>
+#include <phonon/mediasource.h>
+#include <phonon/mediaobjectinterface.h>
#include <QScopedPointer>
#include <QTimer>
@@ -75,6 +75,10 @@ public:
virtual qint32 transitionTime() const;
virtual void setTransitionTime(qint32);
+ // MediaNode
+ void connectMediaObject(MediaObject *mediaObject);
+ void disconnectMediaObject(MediaObject *mediaObject);
+
/**
* This class owns the AbstractPlayer, and will delete it upon
* destruction.
@@ -83,30 +87,28 @@ public:
void setVideoOutput(VideoOutput* videoOutput);
- virtual bool activateOnMediaObject(MediaObject *);
-
public Q_SLOTS:
void volumeChanged(qreal volume);
+ void switchToNextSource();
Q_SIGNALS:
+ void abstractPlayerChanged(AbstractPlayer *player);
void totalTimeChanged(qint64 length);
void hasVideoChanged(bool hasVideo);
void seekableChanged(bool seekable);
- // TODO: emit bufferStatus from MediaObject
void bufferStatus(int);
- // TODO: emit aboutToFinish from MediaObject
void aboutToFinish();
- // TODO: emit prefinishMarkReached from MediaObject
- void prefinishMarkReached(qint32);
+ void prefinishMarkReached(qint32 remaining);
// TODO: emit metaDataChanged from MediaObject
void metaDataChanged(const QMultiMap<QString, QString>& metaData);
void currentSourceChanged(const MediaSource& source);
- void stateChanged(Phonon::State oldState,
- Phonon::State newState);
+ void stateChanged(Phonon::State newState,
+ Phonon::State oldState);
void finished();
void tick(qint64 time);
private:
+ void switchToSource(const MediaSource &source);
void createPlayer(const MediaSource &source);
bool openRecognizer();
@@ -123,6 +125,10 @@ private:
RApaLsSession m_recognizer;
RFs m_fileServer;
+ MediaSource m_source;
+ MediaSource m_nextSource;
+ bool m_nextSourceSet;
+
// Storing the file handle here to work around KErrInUse error
// from MMF player utility OpenFileL functions
RFile m_file;
diff --git a/src/3rdparty/phonon/mmf/mmf_medianode.cpp b/src/3rdparty/phonon/mmf/mmf_medianode.cpp
index 253c5e7..ca413d9 100644
--- a/src/3rdparty/phonon/mmf/mmf_medianode.cpp
+++ b/src/3rdparty/phonon/mmf/mmf_medianode.cpp
@@ -29,92 +29,123 @@ using namespace Phonon::MMF;
\internal
*/
-MMF::MediaNode::MediaNode(QObject *parent) : QObject::QObject(parent)
- , m_source(0)
- , m_target(0)
- , m_isApplied(false)
+MMF::MediaNode::MediaNode(QObject *parent)
+ : QObject(parent)
+ , m_mediaObject(qobject_cast<MediaObject *>(this))
+ , m_input(0)
{
-}
-
-bool MMF::MediaNode::connectMediaNode(MediaNode *target)
-{
- m_target = target;
- m_target->setSource(this);
- return applyNodesOnMediaObject(target);
}
-bool MMF::MediaNode::disconnectMediaNode(MediaNode *target)
+MMF::MediaNode::~MediaNode()
{
- Q_UNUSED(target);
- m_target = 0;
- m_isApplied = false;
- return true;
+ // Phonon framework ensures nodes are disconnected before being destroyed.
+ Q_ASSERT_X(!m_mediaObject, Q_FUNC_INFO,
+ "Media node not disconnected before destruction");
}
-void MMF::MediaNode::setSource(MediaNode *source)
+bool MMF::MediaNode::connectOutput(MediaNode *output)
{
- m_source = source;
+ Q_ASSERT_X(output, Q_FUNC_INFO, "Null output pointer");
+
+ bool connected = false;
+
+ // Check that this connection will not result in a graph which
+ // containing more than one MediaObject
+ const bool mediaObjectMisMatch =
+ m_mediaObject
+ && output->m_mediaObject
+ && m_mediaObject != output->m_mediaObject;
+
+ const bool canConnect =
+ !output->isMediaObject()
+ && !output->m_input
+ && !m_outputs.contains(output);
+
+ if (canConnect && !mediaObjectMisMatch) {
+ output->m_input = this;
+ m_outputs += output;
+ updateMediaObject();
+ connected = true;
+ }
+
+ return connected;
}
-MMF::MediaNode *MMF::MediaNode::source() const
+bool MMF::MediaNode::disconnectOutput(MediaNode *output)
{
- return m_source;
+ Q_ASSERT_X(output, Q_FUNC_INFO, "Null output pointer");
+
+ bool disconnected = false;
+
+ if (m_outputs.contains(output) && this == output->m_input) {
+ output->m_input = 0;
+ const bool removed = m_outputs.removeOne(output);
+ Q_ASSERT_X(removed, Q_FUNC_INFO, "Output removal failed");
+
+ Q_ASSERT_X(!m_outputs.contains(output), Q_FUNC_INFO,
+ "Output list contains duplicate entries");
+
+ // Perform traversal across each of the two graphs separately
+ updateMediaObject();
+ output->updateMediaObject();
+
+ disconnected = true;
+ }
+
+ return disconnected;
}
-MMF::MediaNode *MMF::MediaNode::target() const
+bool MMF::MediaNode::isMediaObject() const
{
- return m_target;
+ return (qobject_cast<const MediaObject *>(this) != 0);
}
-bool MMF::MediaNode::applyNodesOnMediaObject(MediaNode *)
+void MMF::MediaNode::updateMediaObject()
{
- // Algorithmically, this can be expressed in a more efficient way by
- // exercising available assumptions, but it complicates code for input
- // data(length of the graph) which typically is very small.
-
- // First, we go to the very beginning of the graph.
- MMF::MediaNode *current = this;
- do {
- MediaNode *const candidate = current->source();
- if (candidate)
- current = candidate;
- else
- break;
- }
- while (current);
-
- // Now we do two things, while walking to the other end:
- // 1. Find the MediaObject, if present
- // 2. Collect a list of all unapplied MediaNodes
-
- QList<MediaNode *> unapplied;
- MMF::MediaObject *mo = 0;
+ QList<MediaNode *> nodes;
+ MediaObject *mediaObject = 0;
- do {
- if (!current->m_isApplied)
- unapplied.append(current);
+ // Traverse the graph, collecting a list of nodes, and locating
+ // the MediaObject node, if present
+ visit(nodes, mediaObject);
- if (!mo)
- mo = qobject_cast<MMF::MediaObject *>(current);
+ MediaNode *node = 0;
+ foreach(node, nodes)
+ node->setMediaObject(mediaObject);
+}
- current = current->target();
+void MMF::MediaNode::setMediaObject(MediaObject *mediaObject)
+{
+ if(!isMediaObject() && m_mediaObject != mediaObject) {
+ if (!mediaObject)
+ disconnectMediaObject(m_mediaObject);
+ else {
+ Q_ASSERT_X(!m_mediaObject, Q_FUNC_INFO, "MediaObject already set");
+ connectMediaObject(mediaObject);
+ }
+ m_mediaObject = mediaObject;
}
- while (current);
+}
- // Now, lets activate all the objects, if we found the MediaObject.
+void MMF::MediaNode::visit(QList<MediaNode *>& visited, MediaObject*& mediaObject)
+{
+ if (isMediaObject()) {
+ // There can never be more than one MediaObject per graph, due to the
+ // mediaObjectMisMatch test in connectOutput().
+ Q_ASSERT_X(!mediaObject, Q_FUNC_INFO, "MediaObject already found");
+ mediaObject = static_cast<MediaObject *>(this);
+ }
- if (mo) {
- for (int i = 0; i < unapplied.count(); ++i) {
- MediaNode *const at = unapplied.at(i);
+ visited += this;
- // We don't want to apply MediaObject on itself.
- if (at != mo)
- at->activateOnMediaObject(mo);
- }
- }
+ if (m_input && !visited.contains(m_input))
+ m_input->visit(visited, mediaObject);
- return true;
+ MediaNode *output = 0;
+ foreach (output, m_outputs)
+ if (!visited.contains(output))
+ output->visit(visited, mediaObject);
}
QT_END_NAMESPACE
diff --git a/src/3rdparty/phonon/mmf/mmf_medianode.h b/src/3rdparty/phonon/mmf/mmf_medianode.h
index 4616ff1..f2f64e0 100644
--- a/src/3rdparty/phonon/mmf/mmf_medianode.h
+++ b/src/3rdparty/phonon/mmf/mmf_medianode.h
@@ -20,7 +20,7 @@ along with this library. If not, see <http://www.gnu.org/licenses/>.
#define PHONON_MMF_MEDIANODE_H
#include <QObject>
-#include <Phonon/EffectInterface>
+#include <phonon/effectinterface.h>
#include "audioplayer.h"
QT_BEGIN_NAMESPACE
@@ -43,54 +43,62 @@ class MediaObject;
/**
* @short Base class for all nodes in the MMF backend.
*
- * MediaNode is the base class for all nodes in the chain for MMF. Currently
- * they are:
+ * MediaNode is the base class for all nodes created by the MMF
+ * backend.
*
- * - MediaObject: a source of media
- * - AbstractEffect: supplying audio effects
- * - AudioOutput: pretty much a dummy interface, but is also MediaNode in order
- * to simplify connection/disconnection.
+ * These nodes may be one of the following types:
*
- * MediaNode provides spectatability into the chain, and also allows the
- * connection code to be written in a polymorphic manner, instead of putting it
- * all in the Backend class. Due to that MMF has no concept of chaining, the
- * order of the nodes in the graph has no meaning.
+ * - MediaObject
+ * This represents the source of media data. It encapsulates the
+ * appropriate MMF client API for playing audio or video.
+ * - AudioOutput
+ * This represents the audio output device. Since the MMF client API
+ * does not expose the output device directly, this backend node
+ * simply forwards volume control commands to the MediaObject.
+ * - VideoWidget
+ * A native widget on which video will be rendered.
+ * - An audio effect, derived form AbstractAudioEffect
+ *
+ * Because the MMF API does not support the concept of a media filter graph,
+ * this class must ensure the following:
+ *
+ * - Each media graph contains at most one MediaObject instance.
+ * - Every non-MediaObject node holds a reference to the MediaObject. This
+ * allows commands to be sent through the graph to the encapsulated MMF client
+ * API.
*/
class MediaNode : public QObject
{
Q_OBJECT
public:
MediaNode(QObject *parent);
+ ~MediaNode();
+
+ bool connectOutput(MediaNode *output);
+ bool disconnectOutput(MediaNode *output);
+
+ virtual void connectMediaObject(MediaObject *mediaObject) = 0;
+ virtual void disconnectMediaObject(MediaObject *mediaObject) = 0;
- virtual bool connectMediaNode(MediaNode *target);
- virtual bool disconnectMediaNode(MediaNode *target);
- void setSource(MediaNode *source);
+private:
+ bool isMediaObject() const;
- MediaNode *source() const;
- MediaNode *target() const;
+ void updateMediaObject();
+ void setMediaObject(MediaObject *mediaObject);
-protected:
- /**
- * When connectMediaNode() is called and a MediaObject is part of
- * the its graph, this function will be called for each MediaNode in the
- * graph for which it hasn't been called yet.
- *
- * The caller guarantees that @p mo is always non-null.
- */
- virtual bool activateOnMediaObject(MediaObject *mo) = 0;
+ typedef QList<const MediaNode *> NodeList;
+ void visit(QList<MediaNode *>& visited, MediaObject*& mediaObject);
private:
- /**
- * Finds a MediaObject anywhere in the graph @p target is apart of, and
- * calls activateOnMediaObject() for all MediaNodes in the graph for which
- * it hasn't been applied to already.
- */
- bool applyNodesOnMediaObject(MediaNode *target);
-
- MediaNode * m_source;
- MediaNode * m_target;
- bool m_isApplied;
+ MediaObject * m_mediaObject;
+
+ // All nodes except MediaObject may have an input
+ MediaNode * m_input;
+
+ // Only MediaObject can have more than one output
+ QList<MediaNode *> m_outputs;
};
+
}
}
diff --git a/src/3rdparty/phonon/mmf/mmf_videoplayer.cpp b/src/3rdparty/phonon/mmf/mmf_videoplayer.cpp
index b6f53ae..127edb4 100644
--- a/src/3rdparty/phonon/mmf/mmf_videoplayer.cpp
+++ b/src/3rdparty/phonon/mmf/mmf_videoplayer.cpp
@@ -44,20 +44,8 @@ using namespace Phonon::MMF;
// Constructor / destructor
//-----------------------------------------------------------------------------
-MMF::VideoPlayer::VideoPlayer()
- : m_wsSession(CCoeEnv::Static()->WsSession())
- , m_screenDevice(*CCoeEnv::Static()->ScreenDevice())
- , m_window(0)
- , m_totalTime(0)
- , m_pendingChanges(false)
- , m_dsaActive(false)
- , m_dsaWasActive(false)
-{
- construct();
-}
-
-MMF::VideoPlayer::VideoPlayer(const AbstractPlayer& player)
- : AbstractMediaPlayer(player)
+MMF::VideoPlayer::VideoPlayer(MediaObject *parent, const AbstractPlayer *player)
+ : AbstractMediaPlayer(parent, player)
, m_wsSession(CCoeEnv::Static()->WsSession())
, m_screenDevice(*CCoeEnv::Static()->ScreenDevice())
, m_window(0)
@@ -78,22 +66,22 @@ void MMF::VideoPlayer::construct()
const TInt priority = 0;
const TMdaPriorityPreference preference = EMdaPriorityPreferenceNone;
- TRAPD(err,
- m_player.reset(CVideoPlayerUtility::NewL
+ CVideoPlayerUtility *player = 0;
+ QT_TRAP_THROWING(player = CVideoPlayerUtility::NewL
(
*this,
priority, preference,
m_wsSession, m_screenDevice,
*m_window,
m_videoRect, m_videoRect
- ))
+ )
);
+ m_player.reset(player);
// CVideoPlayerUtility::NewL starts DSA
m_dsaActive = true;
- if (KErrNone != err)
- changeState(ErrorState);
+ m_player->RegisterForVideoLoadingNotification(*this);
TRACE_EXIT_0();
}
@@ -109,6 +97,11 @@ MMF::VideoPlayer::~VideoPlayer()
TRACE_EXIT_0();
}
+CVideoPlayerUtility* MMF::VideoPlayer::nativePlayer() const
+{
+ return m_player.data();
+}
+
//-----------------------------------------------------------------------------
// Public API
//-----------------------------------------------------------------------------
@@ -127,9 +120,9 @@ void MMF::VideoPlayer::doPause()
TRACE_CONTEXT(VideoPlayer::doPause, EVideoApi);
TRAPD(err, m_player->PauseL());
- if (KErrNone != err) {
+ if (KErrNone != err && state() != ErrorState) {
TRACE("PauseL error %d", err);
- setError(NormalError);
+ setError(tr("Pause failed"), err);
}
}
@@ -142,24 +135,10 @@ void MMF::VideoPlayer::doSeek(qint64 ms)
{
TRACE_CONTEXT(VideoPlayer::doSeek, EVideoApi);
- bool wasPlaying = false;
- if (state() == PlayingState) {
- // The call to SetPositionL does not have any effect if playback is
- // ongoing, so we pause before seeking.
- doPause();
- wasPlaying = true;
- }
-
TRAPD(err, m_player->SetPositionL(TTimeIntervalMicroSeconds(ms * 1000)));
- if (KErrNone == err) {
- if (wasPlaying)
- doPlay();
- }
- else {
- TRACE("SetPositionL error %d", err);
- setError(NormalError);
- }
+ if(KErrNone != err)
+ setError(tr("Seek failed"), err);
}
int MMF::VideoPlayer::setDeviceVolume(int mmfVolume)
@@ -174,6 +153,19 @@ int MMF::VideoPlayer::openFile(RFile& file)
return err;
}
+int MMF::VideoPlayer::openUrl(const QString& url)
+{
+ TRAPD(err, m_player->OpenUrlL(qt_QString2TPtrC(url)));
+ return err;
+}
+
+int MMF::VideoPlayer::bufferStatus() const
+{
+ int result = 0;
+ TRAP_IGNORE(m_player->GetVideoLoadingProgressL(result));
+ return result;
+}
+
void MMF::VideoPlayer::close()
{
m_player->Close();
@@ -200,7 +192,7 @@ qint64 MMF::VideoPlayer::currentTime() const
// If we don't cast away constness here, we simply have to ignore
// the error.
- const_cast<VideoPlayer*>(this)->setError(NormalError);
+ const_cast<VideoPlayer*>(this)->setError(tr("Getting position failed"), err);
}
return result;
@@ -226,7 +218,7 @@ void MMF::VideoPlayer::MvpuoOpenComplete(TInt aError)
if (KErrNone == aError)
m_player->Prepare();
else
- setError(NormalError);
+ setError(tr("Opening clip failed"), aError);
TRACE_EXIT_0();
}
@@ -252,7 +244,7 @@ void MMF::VideoPlayer::MvpuoPrepareComplete(TInt aError)
emit totalTimeChanged(totalTime());
changeState(StoppedState);
} else {
- setError(NormalError);
+ setError(tr("Buffering clip failed"), err);
}
TRACE_EXIT_0();
@@ -277,7 +269,6 @@ void MMF::VideoPlayer::MvpuoFrameReady(CFbsBitmap &aFrame, TInt aError)
TRACE_CONTEXT(VideoPlayer::MvpuoFrameReady, EVideoApi);
TRACE_ENTRY("state %d error %d", state(), aError);
- // TODO
Q_UNUSED(aFrame);
Q_UNUSED(aError); // suppress warnings in release builds
@@ -289,8 +280,9 @@ void MMF::VideoPlayer::MvpuoPlayComplete(TInt aError)
TRACE_CONTEXT(VideoPlayer::MvpuoPlayComplete, EVideoApi)
TRACE_ENTRY("state %d error %d", state(), aError);
- Q_UNUSED(aError); // suppress warnings in release builds
- changeState(StoppedState);
+ // Call base class function which handles end of playback for both
+ // audio and video clips.
+ playbackComplete(aError);
TRACE_EXIT_0();
}
@@ -300,7 +292,6 @@ void MMF::VideoPlayer::MvpuoEvent(const TMMFEvent &aEvent)
TRACE_CONTEXT(VideoPlayer::MvpuoEvent, EVideoApi);
TRACE_ENTRY("state %d", state());
- // TODO
Q_UNUSED(aEvent);
TRACE_EXIT_0();
@@ -308,6 +299,21 @@ void MMF::VideoPlayer::MvpuoEvent(const TMMFEvent &aEvent)
//-----------------------------------------------------------------------------
+// MVideoLoadingObserver callbacks
+//-----------------------------------------------------------------------------
+
+void MMF::VideoPlayer::MvloLoadingStarted()
+{
+ bufferingStarted();
+}
+
+void MMF::VideoPlayer::MvloLoadingComplete()
+{
+ bufferingComplete();
+}
+
+
+//-----------------------------------------------------------------------------
// Video window updates
//-----------------------------------------------------------------------------
@@ -412,7 +418,7 @@ void MMF::VideoPlayer::startDirectScreenAccess()
if(KErrNone == err)
m_dsaActive = true;
else
- setError(NormalError);
+ setError(tr("Video display error"), err);
}
}
@@ -424,7 +430,7 @@ bool MMF::VideoPlayer::stopDirectScreenAccess()
if(KErrNone == err)
m_dsaActive = false;
else
- setError(NormalError);
+ setError(tr("Video display error"), err);
}
return dsaWasActive;
}
@@ -600,7 +606,7 @@ void MMF::VideoPlayer::applyVideoWindowChange()
TRAPD(err, m_player->SetScaleFactorL(m_scaleWidth, m_scaleHeight, antialias));
if(KErrNone != err) {
TRACE("SetScaleFactorL (1) err %d", err);
- setError(NormalError);
+ setError(tr("Video display error"), err);
}
if(KErrNone == err) {
@@ -615,13 +621,13 @@ void MMF::VideoPlayer::applyVideoWindowChange()
if (KErrNone != err) {
TRACE("SetDisplayWindowL err %d", err);
- setError(NormalError);
+ setError(tr("Video display error"), err);
} else {
m_dsaActive = true;
TRAP(err, m_player->SetScaleFactorL(m_scaleWidth, m_scaleHeight, antialias));
if(KErrNone != err) {
TRACE("SetScaleFactorL (2) err %d", err);
- setError(NormalError);
+ setError(tr("Video display error"), err);
}
}
}
diff --git a/src/3rdparty/phonon/mmf/mmf_videoplayer.h b/src/3rdparty/phonon/mmf/mmf_videoplayer.h
index abb1da8..0253ab9 100644
--- a/src/3rdparty/phonon/mmf/mmf_videoplayer.h
+++ b/src/3rdparty/phonon/mmf/mmf_videoplayer.h
@@ -39,14 +39,17 @@ namespace MMF
*/
class VideoPlayer : public AbstractMediaPlayer
, public MVideoPlayerUtilityObserver
+ , public MVideoLoadingObserver
{
Q_OBJECT
public:
- VideoPlayer();
- explicit VideoPlayer(const AbstractPlayer& player);
+ VideoPlayer(MediaObject *parent = 0, const AbstractPlayer *player = 0);
virtual ~VideoPlayer();
+ typedef CVideoPlayerUtility NativePlayer;
+ NativePlayer *nativePlayer() const;
+
// AbstractPlayer
virtual void doPlay();
virtual void doPause();
@@ -54,6 +57,8 @@ public:
virtual void doSeek(qint64 milliseconds);
virtual int setDeviceVolume(int mmfVolume);
virtual int openFile(RFile& file);
+ virtual int openUrl(const QString& url);
+ virtual int bufferStatus() const;
virtual void close();
// MediaObjectInterface
@@ -61,12 +66,12 @@ public:
virtual qint64 currentTime() const;
virtual qint64 totalTime() const;
- // MVideoPlayerUtilityObserver
- virtual void MvpuoOpenComplete(TInt aError);
- virtual void MvpuoPrepareComplete(TInt aError);
- virtual void MvpuoFrameReady(CFbsBitmap &aFrame, TInt aError);
- virtual void MvpuoPlayComplete(TInt aError);
- virtual void MvpuoEvent(const TMMFEvent &aEvent);
+ // AbstractPlayer
+ virtual void videoOutputChanged();
+
+ // AbstractMediaPlayer
+ virtual int numberOfMetaDataEntries() const;
+ virtual QPair<QString, QString> metaDataEntry(int index) const;
public Q_SLOTS:
void videoWindowChanged();
@@ -80,12 +85,8 @@ private:
void doPrepareCompleteL(TInt aError);
- // AbstractPlayer
- virtual void videoOutputChanged();
-
void getVideoWindow();
void initVideoOutput();
-
void updateVideoRect();
void applyPendingChanges();
@@ -94,12 +95,20 @@ private:
void startDirectScreenAccess();
bool stopDirectScreenAccess();
- // AbstractMediaPlayer
- virtual int numberOfMetaDataEntries() const;
- virtual QPair<QString, QString> metaDataEntry(int index) const;
+private:
+ // MVideoPlayerUtilityObserver
+ virtual void MvpuoOpenComplete(TInt aError);
+ virtual void MvpuoPrepareComplete(TInt aError);
+ virtual void MvpuoFrameReady(CFbsBitmap &aFrame, TInt aError);
+ virtual void MvpuoPlayComplete(TInt aError);
+ virtual void MvpuoEvent(const TMMFEvent &aEvent);
+
+ // MVideoLoadingObserver
+ virtual void MvloLoadingStarted();
+ virtual void MvloLoadingComplete();
private:
- QScopedPointer<CVideoPlayerUtility> m_player;
+ QScopedPointer<NativePlayer> m_player;
// Not owned
RWsSession& m_wsSession;
diff --git a/src/3rdparty/phonon/mmf/objectdump.cpp b/src/3rdparty/phonon/mmf/objectdump.cpp
index 3d10be4..778cde9 100644
--- a/src/3rdparty/phonon/mmf/objectdump.cpp
+++ b/src/3rdparty/phonon/mmf/objectdump.cpp
@@ -390,7 +390,7 @@ void QVisitorPrivate::dumpNode
// No annotations - just dump the object pointer
const bool isNodeLine = true;
QByteArray buffer = branchBuffer(branches, isNodeLine, isLastChild);
- qDebug() << 0; // TODO
+ qDebug() << 0;
}
else {
// Dump annotations
diff --git a/src/3rdparty/phonon/mmf/stereowidening.cpp b/src/3rdparty/phonon/mmf/stereowidening.cpp
new file mode 100644
index 0000000..f90651b
--- /dev/null
+++ b/src/3rdparty/phonon/mmf/stereowidening.cpp
@@ -0,0 +1,93 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library is free software: you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation, either version 2.1 or 3 of the License.
+
+This library 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 Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with this library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include <StereoWideningBase.h>
+#include "stereowidening.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace Phonon;
+using namespace Phonon::MMF;
+
+// Define functions which depend on concrete native effect class name
+PHONON_MMF_DEFINE_EFFECT_FUNCTIONS(StereoWidening)
+
+/*! \class MMF::StereoWidening
+ \internal
+*/
+
+StereoWidening::StereoWidening(QObject *parent, const QList<EffectParameter>& parameters)
+ : AbstractAudioEffect::AbstractAudioEffect(parent, parameters)
+{
+
+}
+
+int StereoWidening::parameterChanged(const EffectParameter &param,
+ const QVariant &value)
+{
+ Q_ASSERT_X(param.id() == ParameterBase, Q_FUNC_INFO, "Invalid parameter ID");
+
+ const qreal externalLevel = value.toReal();
+ const int internalLevel = param.toInternalValue(externalLevel);
+
+ TRAPD(err, concreteEffect()->SetStereoWideningLevelL(internalLevel));
+
+ return err;
+}
+
+//-----------------------------------------------------------------------------
+// Static functions
+//-----------------------------------------------------------------------------
+
+const char* StereoWidening::description()
+{
+ return "Stereo widening";
+}
+
+bool StereoWidening::getParameters(CMdaAudioOutputStream *stream,
+ QList<EffectParameter> &parameters)
+{
+ bool supported = false;
+
+ QScopedPointer<CStereoWidening> effect;
+ TRAPD(err, effect.reset(CStereoWidening::NewL(*stream)));
+
+ if (KErrNone == err) {
+ supported = true;
+
+ const qreal defaultValue =
+ Phonon::MMF::EffectParameter::toExternalValue
+ (effect->StereoWideningLevel(), 0, 100);
+
+ EffectParameter param(
+ /* parameterId */ ParameterBase,
+ /* name */ tr("Level (%)"),
+ /* hints */ EffectParameter::IntegerHint,
+ /* defaultValue */ QVariant(defaultValue),
+ /* minimumValue */ QVariant(qreal(-1.0)),
+ /* maximumValue */ QVariant(qreal(+1.0)));
+
+ param.setInternalRange(0, 100);
+ parameters.append(param);
+ }
+
+ return supported;
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/3rdparty/phonon/mmf/stereowidening.h b/src/3rdparty/phonon/mmf/stereowidening.h
new file mode 100644
index 0000000..c967e37
--- /dev/null
+++ b/src/3rdparty/phonon/mmf/stereowidening.h
@@ -0,0 +1,62 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library is free software: you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation, either version 2.1 or 3 of the License.
+
+This library 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 Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with this library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef PHONON_MMF_STEREOWIDENING_H
+#define PHONON_MMF_STEREOWIDENING_H
+
+#include "abstractaudioeffect.h"
+
+class CStereoWidening;
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace MMF
+{
+/**
+ * @short A "bass boost" effect.
+ */
+class StereoWidening : public AbstractAudioEffect
+{
+ Q_OBJECT
+public:
+ StereoWidening(QObject *parent, const QList<EffectParameter>& parameters);
+
+ // Static interface required by EffectFactory
+ static const char* description();
+ static bool getParameters(CMdaAudioOutputStream *stream,
+ QList<EffectParameter>& parameters);
+
+protected:
+ // AbstractAudioEffect
+ virtual void createEffect(AudioPlayer::NativePlayer *player);
+ virtual int parameterChanged(const EffectParameter &param,
+ const QVariant &value);
+
+private:
+ CStereoWidening *concreteEffect();
+
+};
+}
+}
+
+QT_END_NAMESPACE
+
+#endif
+
diff --git a/src/3rdparty/phonon/mmf/utils.cpp b/src/3rdparty/phonon/mmf/utils.cpp
index d728fcf..2d17bd2 100644
--- a/src/3rdparty/phonon/mmf/utils.cpp
+++ b/src/3rdparty/phonon/mmf/utils.cpp
@@ -18,6 +18,7 @@ along with this library. If not, see <http://www.gnu.org/licenses/>.
#include "utils.h"
#include <e32std.h>
+#include <mmf/common/mmferrors.h>
QT_BEGIN_NAMESPACE
@@ -69,6 +70,101 @@ MMF::MediaType MMF::Utils::mimeTypeToMediaType(const TDesC& mimeType)
return result;
}
+QString MMF::Utils::symbianErrorToString(int errorCode)
+{
+ /**
+ * Here we translate only the error codes which are likely to be
+ * meaningful to the user. For example, when an error occurs
+ * during opening of a media file, displaying "not found" or
+ * "permission denied" is informative. On the other hand,
+ * differentiating between KErrGeneral and KErrArgument at the UI
+ * level does not make sense.
+ */
+ switch (errorCode)
+ {
+ // System-wide errors
+ case KErrNone:
+ return tr("No error");
+ case KErrNotFound:
+ return tr("Not found");
+ case KErrNoMemory:
+ return tr("Out of memory");
+ case KErrNotSupported:
+ return tr("Not supported");
+ case KErrOverflow:
+ return tr("Overflow");
+ case KErrUnderflow:
+ return tr("Underflow");
+ case KErrAlreadyExists:
+ return tr("Already exists");
+ case KErrPathNotFound:
+ return tr("Path not found");
+ case KErrInUse:
+ return tr("In use");
+ case KErrNotReady:
+ return tr("Not ready");
+ case KErrAccessDenied:
+ return tr("Access denied");
+ case KErrCouldNotConnect:
+ return tr("Could not connect");
+ case KErrDisconnected:
+ return tr("Disconnected");
+ case KErrPermissionDenied:
+ return tr("Permission denied");
+
+ // Multimedia framework errors
+ case KErrMMNotEnoughBandwidth:
+ return tr("Insufficient bandwidth");
+ case KErrMMSocketServiceNotFound:
+ case KErrMMServerSocket:
+ return tr("Network unavailable");
+ case KErrMMNetworkRead:
+ case KErrMMNetworkWrite:
+ case KErrMMUDPReceive:
+ return tr("Network communication error");
+ case KErrMMServerNotSupported:
+ return tr("Streaming not supported");
+ case KErrMMServerAlert:
+ return tr("Server alert");
+ case KErrMMInvalidProtocol:
+ return tr("Invalid protocol");
+ case KErrMMInvalidURL:
+ return tr("Invalid URL");
+ case KErrMMMulticast:
+ return tr("Multicast error");
+ case KErrMMProxyServer:
+ case KErrMMProxyServerConnect:
+ return tr("Proxy server error");
+ case KErrMMProxyServerNotSupported:
+ return tr("Proxy server not supported");
+ case KErrMMAudioDevice:
+ return tr("Audio output error");
+ case KErrMMVideoDevice:
+ return tr("Video output error");
+ case KErrMMDecoder:
+ return tr("Decoder error");
+ case KErrMMPartialPlayback:
+ return tr("Audio or video components could not be played");
+ case KErrMMDRMNotAuthorized:
+ return tr("DRM error");
+
+ /*
+ // We don't use QoS settings
+ case KErrMMQosLowBandwidth:
+ case KErrMMQosUnsupportedTrafficClass:
+ case KErrMMQosPoorTrafficClass:
+ case KErrMMQosUnsupportedParameters:
+ case KErrMMQosPoorParameters:
+ case KErrMMQosNotSupported:
+ */
+
+ // Catch-all for errors other than those above
+ default:
+ {
+ return tr("Unknown error (%1)").arg(errorCode);
+ }
+ }
+}
#ifndef QT_NO_DEBUG
diff --git a/src/3rdparty/phonon/mmf/utils.h b/src/3rdparty/phonon/mmf/utils.h
index 7e363e8..56ccafc 100644
--- a/src/3rdparty/phonon/mmf/utils.h
+++ b/src/3rdparty/phonon/mmf/utils.h
@@ -21,7 +21,7 @@ along with this library. If not, see <http://www.gnu.org/licenses/>.
#include <private/qcore_symbian_p.h>
#include <e32debug.h> // for RDebug
-
+#include <QtCore/QCoreApplication> // for Q_DECLARE_TR_FUNCTIONS
#include <QColor>
#include "defs.h"
@@ -38,35 +38,44 @@ namespace MMF
enum PanicCode {
InvalidStatePanic = 1,
InvalidMediaTypePanic = 2,
- InvalidBackendInterfaceClass = 3
+ InvalidBackendInterfaceClass = 3,
+ AudioUtilityUrlNotSupported = 4
};
-namespace Utils
+class Utils
{
+ Q_DECLARE_TR_FUNCTIONS(Utils)
+
+public:
/**
* Raise a fatal exception
*/
-void panic(PanicCode code);
+static void panic(PanicCode code);
/**
* Determines whether the provided MIME type is an audio or video
* type. If it is neither, the function returns MediaTypeUnknown.
*/
-MediaType mimeTypeToMediaType(const TDesC& mimeType);
+static MediaType mimeTypeToMediaType(const TDesC& mimeType);
+
+/**
+ * Translates a Symbian error code into a user-readable string.
+ */
+static QString symbianErrorToString(int errorCode);
#ifndef QT_NO_DEBUG
/**
* Retrieve color of specified pixel from the screen.
*/
-QColor getScreenPixel(const QPoint& pos);
+static QColor getScreenPixel(const QPoint& pos);
/**
* Samples a small number of pixels from the screen, and dumps their
* colors to the debug log.
*/
-void dumpScreenPixelSample();
+static void dumpScreenPixelSample();
#endif
-}
+};
/**
* Available trace categories;
diff --git a/src/3rdparty/phonon/mmf/videooutput.h b/src/3rdparty/phonon/mmf/videooutput.h
index 2788401..3e9c036 100644
--- a/src/3rdparty/phonon/mmf/videooutput.h
+++ b/src/3rdparty/phonon/mmf/videooutput.h
@@ -24,7 +24,7 @@ along with this library. If not, see <http://www.gnu.org/licenses/>.
#include <QRect>
#include "defs.h"
-#include <Phonon/VideoWidget>
+#include <phonon/videowidget.h>
#include <e32std.h>
class RWindowBase;
diff --git a/src/3rdparty/phonon/mmf/videowidget.cpp b/src/3rdparty/phonon/mmf/videowidget.cpp
index bd22307..bc9acfd 100644
--- a/src/3rdparty/phonon/mmf/videowidget.cpp
+++ b/src/3rdparty/phonon/mmf/videowidget.cpp
@@ -157,10 +157,18 @@ QWidget* MMF::VideoWidget::widget()
return m_videoOutput.data();
}
-bool MMF::VideoWidget::activateOnMediaObject(MediaObject *mo)
+//-----------------------------------------------------------------------------
+// MediaNode
+//-----------------------------------------------------------------------------
+
+void MMF::VideoWidget::connectMediaObject(MediaObject *mediaObject)
+{
+ mediaObject->setVideoOutput(m_videoOutput.data());
+}
+
+void MMF::VideoWidget::disconnectMediaObject(MediaObject *mediaObject)
{
- mo->setVideoOutput(m_videoOutput.data());
- return true;
+ mediaObject->setVideoOutput(0);
}
QT_END_NAMESPACE
diff --git a/src/3rdparty/phonon/mmf/videowidget.h b/src/3rdparty/phonon/mmf/videowidget.h
index 2f0978b..899dca6 100644
--- a/src/3rdparty/phonon/mmf/videowidget.h
+++ b/src/3rdparty/phonon/mmf/videowidget.h
@@ -23,8 +23,8 @@ along with this library. If not, see <http://www.gnu.org/licenses/>.
#include "videooutput.h"
#include <QtGui/QWidget>
-#include <Phonon/VideoWidget>
-#include <Phonon/VideoWidgetInterface>
+#include <phonon/videowidget.h>
+#include <phonon/videowidgetinterface.h>
QT_BEGIN_NAMESPACE
@@ -61,7 +61,9 @@ public:
virtual QWidget *widget();
protected:
- virtual bool activateOnMediaObject(MediaObject *mo);
+ // MediaNode
+ void connectMediaObject(MediaObject *mediaObject);
+ void disconnectMediaObject(MediaObject *mediaObject);
private:
QScopedPointer<VideoOutput> m_videoOutput;
diff --git a/src/3rdparty/phonon/phonon/effectwidget.cpp b/src/3rdparty/phonon/phonon/effectwidget.cpp
index 2334d7f..a2fe50f 100644
--- a/src/3rdparty/phonon/phonon/effectwidget.cpp
+++ b/src/3rdparty/phonon/phonon/effectwidget.cpp
@@ -15,7 +15,7 @@
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
- You should have received a copy of the GNU Lesser General Public
+ You should have received a copy of the GNU Lesser General Public
License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
@@ -151,7 +151,7 @@ void EffectWidgetPrivate::autogenerateUi()
bool minValueOk = false;
bool maxValueOk = false;
const int minValue = para.minimumValue().toInt(&minValueOk);
- const int maxValue = para.minimumValue().toInt(&maxValueOk);
+ const int maxValue = para.maximumValue().toInt(&maxValueOk);
sb->setRange(minValueOk ? minValue : DEFAULT_MIN_INT, maxValueOk ? maxValue : DEFAULT_MAX_INT);
sb->setValue(value.toInt());