summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGareth Stockwell <ext-gareth.stockwell@nokia.com>2009-12-04 11:49:12 +0000
committerGareth Stockwell <ext-gareth.stockwell@nokia.com>2009-12-08 13:07:39 +0000
commit3f648dc075689e2ffedda2769cc76b4a56fb1073 (patch)
treee216758e5d86e14c7d3d8630796e11f355b4add4
parent8e21fc62fe40c8e393007516958c216ad8dbd629 (diff)
downloadqt4-tools-3f648dc075689e2ffedda2769cc76b4a56fb1073.tar.gz
Implemented node disconnection in Phonon MMF backend
Task-number: QTBUG-4663 Reviewed-by: Frans Englich
-rw-r--r--src/3rdparty/phonon/mmf/abstractaudioeffect.cpp58
-rw-r--r--src/3rdparty/phonon/mmf/abstractaudioeffect.h27
-rw-r--r--src/3rdparty/phonon/mmf/audioequalizer.cpp38
-rw-r--r--src/3rdparty/phonon/mmf/audioequalizer.h13
-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.cpp15
-rw-r--r--src/3rdparty/phonon/mmf/audioplayer.h21
-rw-r--r--src/3rdparty/phonon/mmf/backend.cpp29
-rw-r--r--src/3rdparty/phonon/mmf/bassboost.cpp22
-rw-r--r--src/3rdparty/phonon/mmf/bassboost.h12
-rw-r--r--src/3rdparty/phonon/mmf/effectfactory.cpp2
-rw-r--r--src/3rdparty/phonon/mmf/mediaobject.cpp25
-rw-r--r--src/3rdparty/phonon/mmf/mediaobject.h6
-rw-r--r--src/3rdparty/phonon/mmf/mmf_medianode.cpp153
-rw-r--r--src/3rdparty/phonon/mmf/mmf_medianode.h76
-rw-r--r--src/3rdparty/phonon/mmf/mmf_videoplayer.cpp5
-rw-r--r--src/3rdparty/phonon/mmf/mmf_videoplayer.h5
-rw-r--r--src/3rdparty/phonon/mmf/videowidget.cpp14
-rw-r--r--src/3rdparty/phonon/mmf/videowidget.h4
20 files changed, 348 insertions, 194 deletions
diff --git a/src/3rdparty/phonon/mmf/abstractaudioeffect.cpp b/src/3rdparty/phonon/mmf/abstractaudioeffect.cpp
index a55924992d..8c73027a92 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,18 +36,13 @@ using namespace Phonon::MMF;
*/
AbstractAudioEffect::AbstractAudioEffect(QObject *parent,
- const QList<EffectParameter> &params) : MediaNode::MediaNode(parent)
- , m_params(params)
+ const QList<EffectParameter> &params)
+ : MediaNode::MediaNode(parent)
+ , m_player(0)
+ , m_params(params)
{
}
-bool AbstractAudioEffect::disconnectMediaNode(MediaNode *target)
-{
- MediaNode::disconnectMediaNode(target);
- m_effect.reset();
- return true;
-}
-
QList<EffectParameter> AbstractAudioEffect::parameters() const
{
return m_params;
@@ -61,21 +58,44 @@ QVariant AbstractAudioEffect::parameterValue(const EffectParameter &queriedParam
return val;
}
-bool AbstractAudioEffect::activateOnMediaObject(MediaObject *mo)
-{
- AudioPlayer *const ap = qobject_cast<AudioPlayer *>(mo->abstractPlayer());
-
- if (ap)
- return activateOn(ap->player());
- else
- return true;
-}
-
void AbstractAudioEffect::setParameterValue(const EffectParameter &param,
const QVariant &newValue)
{
m_values.insert(param.id(), newValue);
parameterChanged(param.id(), newValue);
+ // TODO: handle audio effect errors
+ TRAP_IGNORE(m_effect->ApplyL());
+}
+
+void AbstractAudioEffect::connectMediaObject(MediaObject *mediaObject)
+{
+ Q_ASSERT_X(!m_player, Q_FUNC_INFO, "Player already connected");
+ Q_ASSERT_X(!m_effect.data(), Q_FUNC_INFO, "Effect already created");
+
+ AbstractMediaPlayer *const player =
+ qobject_cast<AbstractMediaPlayer *>(mediaObject->abstractPlayer());
+
+ if (player) {
+ m_player = player;
+
+ if (AudioPlayer *audioPlayer = qobject_cast<AudioPlayer *>(player)) {
+ connectAudioPlayer(audioPlayer->nativePlayer());
+ } else {
+ VideoPlayer *videoPlayer = qobject_cast<VideoPlayer *>(player);
+ Q_ASSERT_X(videoPlayer, Q_FUNC_INFO, "Player type not recognised");
+ connectVideoPlayer(videoPlayer->nativePlayer());
+ }
+
+ applyParameters();
+ // TODO: handle audio effect errors
+ TRAP_IGNORE(m_effect->EnableL());
+ }
+}
+
+void AbstractAudioEffect::disconnectMediaObject(MediaObject * /*mediaObject*/)
+{
+ m_player = 0;
+ m_effect.reset();
}
QT_END_NAMESPACE
diff --git a/src/3rdparty/phonon/mmf/abstractaudioeffect.h b/src/3rdparty/phonon/mmf/abstractaudioeffect.h
index 01542c9fa2..10578af93a 100644
--- a/src/3rdparty/phonon/mmf/abstractaudioeffect.h
+++ b/src/3rdparty/phonon/mmf/abstractaudioeffect.h
@@ -19,15 +19,16 @@ 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 "audioplayer.h"
+#include "mmf_medianode.h"
+#include "mmf_videoplayer.h"
QT_BEGIN_NAMESPACE
@@ -35,6 +36,7 @@ namespace Phonon
{
namespace MMF
{
+class AbstractMediaPlayer;
/**
* @short Base class for all effects for MMF.
@@ -66,8 +68,6 @@ public:
virtual void setParameterValue(const EffectParameter &,
const QVariant &newValue);
- virtual bool disconnectMediaNode(MediaNode *target);
-
enum Type
{
EffectAudioEqualizer = 1,
@@ -81,21 +81,26 @@ public:
};
protected:
- virtual bool activateOn(CPlayerType *player) = 0;
+ // MediaNode
+ void connectMediaObject(MediaObject *mediaObject);
+ void disconnectMediaObject(MediaObject *mediaObject);
+
+ virtual void connectAudioPlayer(AudioPlayer::NativePlayer *player) = 0;
+ virtual void connectVideoPlayer(VideoPlayer::NativePlayer *player) = 0;
+ virtual void applyParameters() = 0;
+
virtual void parameterChanged(const int id,
const QVariant &value) = 0;
- /**
- * Part of the implementation of AbstractAudioEffect. Forwards the call to
- * activateOn(), essentially.
- */
- virtual bool activateOnMediaObject(MediaObject *mo);
-
+protected:
QScopedPointer<CAudioEffect> m_effect;
+
private:
+ AbstractMediaPlayer * m_player;
const QList<EffectParameter> m_params;
QHash<int, QVariant> m_values;
};
+
}
}
diff --git a/src/3rdparty/phonon/mmf/audioequalizer.cpp b/src/3rdparty/phonon/mmf/audioequalizer.cpp
index 7cc9bc713b..51f1c3216c 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
@@ -34,18 +35,43 @@ AudioEqualizer::AudioEqualizer(QObject *parent) : AbstractAudioEffect::AbstractA
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()));
+ if (m_effect.data()) {
+ const int band = pid;
+ const int level = value.toInt();
+ setBandLevel(band, level);
+ }
}
-bool AudioEqualizer::activateOn(CPlayerType *player)
+void AudioEqualizer::connectAudioPlayer(AudioPlayer::NativePlayer *player)
{
CAudioEqualizer *ptr = 0;
QT_TRAP_THROWING(ptr = CAudioEqualizer::NewL(*player));
m_effect.reset(ptr);
+}
- return true;
+void AudioEqualizer::connectVideoPlayer(VideoPlayer::NativePlayer *player)
+{
+ CAudioEqualizer *ptr = 0;
+ QT_TRAP_THROWING(ptr = CAudioEqualizer::NewL(*player));
+ m_effect.reset(ptr);
+}
+
+void AudioEqualizer::applyParameters()
+{
+ Q_ASSERT_X(m_effect.data(), Q_FUNC_INFO, "Effect not created");
+ EffectParameter param;
+ foreach (param, parameters()) {
+ const int band = param.id();
+ const int level = parameterValue(param).toInt();
+ setBandLevel(band, level);
+ }
+}
+
+void AudioEqualizer::setBandLevel(int band, int level)
+{
+ CAudioEqualizer *const effect = static_cast<CAudioEqualizer *>(m_effect.data());
+ // TODO: handle audio effect errors
+ TRAP_IGNORE(effect->SetBandLevelL(band, level));
}
QList<EffectParameter> AudioEqualizer::createParams()
@@ -57,7 +83,7 @@ QList<EffectParameter> AudioEqualizer::createParams()
AudioPlayer dummyPlayer;
CAudioEqualizer *eqPtr = 0;
- QT_TRAP_THROWING(eqPtr = CAudioEqualizer::NewL(*dummyPlayer.player());)
+ QT_TRAP_THROWING(eqPtr = CAudioEqualizer::NewL(*dummyPlayer.nativePlayer()));
QScopedPointer<CAudioEqualizer> e(eqPtr);
TInt32 dbMin;
diff --git a/src/3rdparty/phonon/mmf/audioequalizer.h b/src/3rdparty/phonon/mmf/audioequalizer.h
index d4c81658a7..9910ea4ccb 100644
--- a/src/3rdparty/phonon/mmf/audioequalizer.h
+++ b/src/3rdparty/phonon/mmf/audioequalizer.h
@@ -19,7 +19,6 @@ 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"
QT_BEGIN_NAMESPACE
@@ -43,14 +42,18 @@ public:
AudioEqualizer(QObject *parent);
protected:
- virtual void parameterChanged(const int id,
- const QVariant &value);
+ // AbstractAudioEffect
+ virtual void connectAudioPlayer(AudioPlayer::NativePlayer *player);
+ virtual void connectVideoPlayer(VideoPlayer::NativePlayer *player);
+ virtual void applyParameters();
+ virtual void parameterChanged(const int id, const QVariant &value);
- virtual bool activateOn(CPlayerType *player);
+private:
+ void setBandLevel(int band, int level);
private:
static QList<EffectParameter> createParams();
- QScopedPointer<CAudioEqualizer> m_bassBoost;
+
};
}
}
diff --git a/src/3rdparty/phonon/mmf/audiooutput.cpp b/src/3rdparty/phonon/mmf/audiooutput.cpp
index d6e0c13be4..c6be20b3de 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 1e1e13478d..67aaa38e9e 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 77488f4081..ee07229520 100644
--- a/src/3rdparty/phonon/mmf/audioplayer.cpp
+++ b/src/3rdparty/phonon/mmf/audioplayer.cpp
@@ -46,8 +46,8 @@ void MMF::AudioPlayer::construct()
TRACE_CONTEXT(AudioPlayer::AudioPlayer, EAudioApi);
TRACE_ENTRY_0();
- CPlayerType *player = 0;
- QT_TRAP_THROWING(player = CPlayerType::NewL(*this, 0, EMdaPriorityPreferenceNone));
+ NativePlayer *player = 0;
+ QT_TRAP_THROWING(player = NativePlayer::NewL(*this, 0, EMdaPriorityPreferenceNone));
m_player.reset(player);
m_player->RegisterForAudioLoadingNotification(*this);
@@ -62,6 +62,11 @@ MMF::AudioPlayer::~AudioPlayer()
TRACE_EXIT_0();
}
+MMF::AudioPlayer::NativePlayer *MMF::AudioPlayer::nativePlayer() const
+{
+ return m_player.data();
+}
+
//-----------------------------------------------------------------------------
// Public API
//-----------------------------------------------------------------------------
@@ -223,12 +228,6 @@ void MMF::AudioPlayer::MapcPlayComplete(TInt aError)
TRACE_EXIT_0();
}
-CPlayerType *MMF::AudioPlayer::player() const
-{
- return m_player.data();
-}
-
-
#ifdef QT_PHONON_MMF_AUDIO_DRM
void MMF::AudioPlayer::MaloLoadingStarted()
{
diff --git a/src/3rdparty/phonon/mmf/audioplayer.h b/src/3rdparty/phonon/mmf/audioplayer.h
index 4c4bcd0231..0eb8bb7f70 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,7 +42,7 @@ namespace MMF
* @short Wrapper over MMF audio client utility
*/
class AudioPlayer : public AbstractMediaPlayer
- , public MPlayerObserverType // typedef
+ , public NativePlayerObserver
, public MAudioLoadingObserver
{
Q_OBJECT
@@ -53,6 +51,14 @@ public:
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();
@@ -76,7 +82,7 @@ public:
/**
* This class owns the pointer.
*/
- CPlayerType *player() const;
+ NativePlayer *player() const;
private:
void construct();
@@ -103,9 +109,10 @@ 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 7e3a67fdd0..0c07f66178 100644
--- a/src/3rdparty/phonon/mmf/backend.cpp
+++ b/src/3rdparty/phonon/mmf/backend.cpp
@@ -139,29 +139,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 mediaSource = static_cast<MediaNode *>(source);
- MediaNode *const mediaTarget = static_cast<MediaNode *>(target);
+ MediaNode *const source = qobject_cast<MediaNode *>(sourceObject);
+ MediaNode *const target = qobject_cast<MediaNode *>(targetObject);
- return mediaSource->connectMediaNode(mediaTarget);
+ 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 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/bassboost.cpp b/src/3rdparty/phonon/mmf/bassboost.cpp
index e34f9e72c3..36069fb431 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
@@ -35,13 +36,26 @@ BassBoost::BassBoost(QObject *parent) : AbstractAudioEffect::AbstractAudioEffect
void BassBoost::parameterChanged(const int,
const QVariant &)
{
- // We should never be called, because we have no parameters.
+ Q_ASSERT_X(false, Q_FUNC_INFO, "BassBoost has not parameters");
}
-bool BassBoost::activateOn(CPlayerType *player)
+void BassBoost::connectAudioPlayer(AudioPlayer::NativePlayer *player)
{
- m_effect.reset(CBassBoost::NewL(*player, true));
- return true;
+ CBassBoost *ptr = 0;
+ QT_TRAP_THROWING(ptr = CBassBoost::NewL(*player));
+ m_effect.reset(ptr);
+}
+
+void BassBoost::connectVideoPlayer(VideoPlayer::NativePlayer *player)
+{
+ CBassBoost *ptr = 0;
+ QT_TRAP_THROWING(ptr = CBassBoost::NewL(*player));
+ m_effect.reset(ptr);
+}
+
+void BassBoost::applyParameters()
+{
+ // No parameters to apply
}
QT_END_NAMESPACE
diff --git a/src/3rdparty/phonon/mmf/bassboost.h b/src/3rdparty/phonon/mmf/bassboost.h
index c16393af63..1b893db69e 100644
--- a/src/3rdparty/phonon/mmf/bassboost.h
+++ b/src/3rdparty/phonon/mmf/bassboost.h
@@ -19,7 +19,6 @@ 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"
QT_BEGIN_NAMESPACE
@@ -41,13 +40,12 @@ public:
BassBoost(QObject *parent);
protected:
- virtual void parameterChanged(const int id,
- const QVariant &value);
+ // AbstractAudioEffect
+ virtual void connectAudioPlayer(AudioPlayer::NativePlayer *player);
+ virtual void connectVideoPlayer(VideoPlayer::NativePlayer *player);
+ virtual void applyParameters();
+ virtual void parameterChanged(const int id, const QVariant &value);
- virtual bool activateOn(CPlayerType *player);
-
-private:
- QScopedPointer<CBassBoost> m_bassBoost;
};
}
}
diff --git a/src/3rdparty/phonon/mmf/effectfactory.cpp b/src/3rdparty/phonon/mmf/effectfactory.cpp
index e9c5e27210..cc94367159 100644
--- a/src/3rdparty/phonon/mmf/effectfactory.cpp
+++ b/src/3rdparty/phonon/mmf/effectfactory.cpp
@@ -113,7 +113,7 @@ bool isEffectSupported()
AudioPlayer audioPlayer;
QScopedPointer<TEffect> eff;
- TRAPD(errorCode, eff.reset(TEffect::NewL(*audioPlayer.player())));
+ TRAPD(errorCode, eff.reset(TEffect::NewL(*audioPlayer.nativePlayer())));
return errorCode != KErrNone;
}
diff --git a/src/3rdparty/phonon/mmf/mediaobject.cpp b/src/3rdparty/phonon/mmf/mediaobject.cpp
index a9a012fab6..4653fee048 100644
--- a/src/3rdparty/phonon/mmf/mediaobject.cpp
+++ b/src/3rdparty/phonon/mmf/mediaobject.cpp
@@ -358,6 +358,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
//-----------------------------------------------------------------------------
@@ -372,12 +391,6 @@ AbstractPlayer *MMF::MediaObject::abstractPlayer() const
return m_player.data();
}
-bool MMF::MediaObject::activateOnMediaObject(MediaObject *)
-{
- // Guess what, we do nothing.
- return true;
-}
-
//-----------------------------------------------------------------------------
// Playlist support
//-----------------------------------------------------------------------------
diff --git a/src/3rdparty/phonon/mmf/mediaobject.h b/src/3rdparty/phonon/mmf/mediaobject.h
index 7c395983f7..668b953264 100644
--- a/src/3rdparty/phonon/mmf/mediaobject.h
+++ b/src/3rdparty/phonon/mmf/mediaobject.h
@@ -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,8 +87,6 @@ public:
void setVideoOutput(VideoOutput* videoOutput);
- virtual bool activateOnMediaObject(MediaObject *);
-
public Q_SLOTS:
void volumeChanged(qreal volume);
void switchToNextSource();
diff --git a/src/3rdparty/phonon/mmf/mmf_medianode.cpp b/src/3rdparty/phonon/mmf/mmf_medianode.cpp
index 253c5e7926..ca413d921d 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 4616ff1bdd..0ed21c4b6b 100644
--- a/src/3rdparty/phonon/mmf/mmf_medianode.h
+++ b/src/3rdparty/phonon/mmf/mmf_medianode.h
@@ -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 877dfb3f59..127edb4201 100644
--- a/src/3rdparty/phonon/mmf/mmf_videoplayer.cpp
+++ b/src/3rdparty/phonon/mmf/mmf_videoplayer.cpp
@@ -97,6 +97,11 @@ MMF::VideoPlayer::~VideoPlayer()
TRACE_EXIT_0();
}
+CVideoPlayerUtility* MMF::VideoPlayer::nativePlayer() const
+{
+ return m_player.data();
+}
+
//-----------------------------------------------------------------------------
// Public API
//-----------------------------------------------------------------------------
diff --git a/src/3rdparty/phonon/mmf/mmf_videoplayer.h b/src/3rdparty/phonon/mmf/mmf_videoplayer.h
index 6200e39de3..0253ab9a1f 100644
--- a/src/3rdparty/phonon/mmf/mmf_videoplayer.h
+++ b/src/3rdparty/phonon/mmf/mmf_videoplayer.h
@@ -47,6 +47,9 @@ public:
VideoPlayer(MediaObject *parent = 0, const AbstractPlayer *player = 0);
virtual ~VideoPlayer();
+ typedef CVideoPlayerUtility NativePlayer;
+ NativePlayer *nativePlayer() const;
+
// AbstractPlayer
virtual void doPlay();
virtual void doPause();
@@ -105,7 +108,7 @@ private:
virtual void MvloLoadingComplete();
private:
- QScopedPointer<CVideoPlayerUtility> m_player;
+ QScopedPointer<NativePlayer> m_player;
// Not owned
RWsSession& m_wsSession;
diff --git a/src/3rdparty/phonon/mmf/videowidget.cpp b/src/3rdparty/phonon/mmf/videowidget.cpp
index bd2230756a..bc9acfd866 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 2f0978b7ca..a876748214 100644
--- a/src/3rdparty/phonon/mmf/videowidget.h
+++ b/src/3rdparty/phonon/mmf/videowidget.h
@@ -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;