From c4fb0864e229ff33e4b454c74116573a9ea79054 Mon Sep 17 00:00:00 2001 From: Frans Englich Date: Mon, 7 Sep 2009 01:22:32 +0200 Subject: Make the MediaObject propagation generic for all kinds of nodes. Previously the MediaObject propagation was only done for effects, but now it's for all kinds of nodes. This is needed for AudioOutput. --- src/3rdparty/phonon/mmf/abstractaudioeffect.cpp | 50 +++++----------------- src/3rdparty/phonon/mmf/abstractaudioeffect.h | 14 +++---- src/3rdparty/phonon/mmf/audioequalizer.cpp | 3 +- src/3rdparty/phonon/mmf/audioequalizer.h | 2 +- src/3rdparty/phonon/mmf/audiooutput.cpp | 6 +++ src/3rdparty/phonon/mmf/audiooutput.h | 8 ++-- src/3rdparty/phonon/mmf/backend.cpp | 4 +- src/3rdparty/phonon/mmf/bassboost.cpp | 3 +- src/3rdparty/phonon/mmf/bassboost.h | 2 +- src/3rdparty/phonon/mmf/mediaobject.cpp | 32 ++------------ src/3rdparty/phonon/mmf/mediaobject.h | 8 ++-- src/3rdparty/phonon/mmf/mmf_medianode.cpp | 56 ++++++++++++++++++++++++- src/3rdparty/phonon/mmf/mmf_medianode.h | 27 ++++++++++-- src/3rdparty/phonon/mmf/videowidget.cpp | 7 ++++ src/3rdparty/phonon/mmf/videowidget.h | 3 ++ src/3rdparty/phonon/phonon/path.cpp | 8 ++-- 16 files changed, 133 insertions(+), 100 deletions(-) diff --git a/src/3rdparty/phonon/mmf/abstractaudioeffect.cpp b/src/3rdparty/phonon/mmf/abstractaudioeffect.cpp index 4c876e1..665b9e4 100644 --- a/src/3rdparty/phonon/mmf/abstractaudioeffect.cpp +++ b/src/3rdparty/phonon/mmf/abstractaudioeffect.cpp @@ -29,7 +29,6 @@ using namespace Phonon::MMF; AbstractAudioEffect::AbstractAudioEffect(QObject *parent, const QList ¶ms) : MediaNode::MediaNode(parent) , m_params(params) - , m_isApplied(false) { } @@ -55,50 +54,21 @@ QVariant AbstractAudioEffect::parameterValue(const EffectParameter &queriedParam return val; } -void AbstractAudioEffect::setParameterValue(const EffectParameter ¶m, - const QVariant &newValue) +bool AbstractAudioEffect::activateOnMediaObject(MediaObject *mo) { - m_values.insert(param.id(), newValue); - parameterChanged(param.id(), newValue); -} + AudioPlayer *const ap = qobject_cast(mo->abstractPlayer()); -bool AbstractAudioEffect::activateBackwardsInChain(MediaNode *target) -{ - // TODO we need to walk forward too. - MediaNode *current = target; - - while (current) { - MMF::MediaObject *const mo = qobject_cast(current); - if(!mo) - continue; - - AudioPlayer *const ap = qobject_cast(mo->abstractPlayer()); - - if (ap) { - activateOn(ap->player()); - // There might be stuff before the mediaobject, but - // that's undefined for us. - return true; - } - else - current = current->source(); - } - - return false; + if (ap) + return activateOn(ap->player()); + else + return true; } -bool AbstractAudioEffect::connectMediaNode(MediaNode *target) +void AbstractAudioEffect::setParameterValue(const EffectParameter ¶m, + const QVariant &newValue) { - /** - * We first call this function, so source() and target() - * is properly set up. - */ - MediaNode::connectMediaNode(target); - - if (!m_isApplied && activateBackwardsInChain(target)) - m_isApplied = true; - - return true; + m_values.insert(param.id(), newValue); + parameterChanged(param.id(), newValue); } QT_END_NAMESPACE diff --git a/src/3rdparty/phonon/mmf/abstractaudioeffect.h b/src/3rdparty/phonon/mmf/abstractaudioeffect.h index 4c2eba3..cf2fb3c 100644 --- a/src/3rdparty/phonon/mmf/abstractaudioeffect.h +++ b/src/3rdparty/phonon/mmf/abstractaudioeffect.h @@ -66,7 +66,6 @@ public: virtual void setParameterValue(const EffectParameter &, const QVariant &newValue); - virtual bool connectMediaNode(MediaNode *target); virtual bool disconnectMediaNode(MediaNode *target); enum Type @@ -83,20 +82,19 @@ public: }; protected: - virtual void activateOn(CPlayerType *player) = 0; + virtual bool activateOn(CPlayerType *player) = 0; virtual void parameterChanged(const int id, const QVariant &value) = 0; - QScopedPointer m_effect; -private: /** - * From @p target, we walk the chain backwards and try to find the media - * object, and apply ourselves to that one. + * Part of the implementation of AbstractAudioEffect. Forwards the call to + * activateOn(), essentially. */ - bool activateBackwardsInChain(MediaNode *target); + virtual bool activateOnMediaObject(MediaObject *mo); + QScopedPointer m_effect; +private: const QList m_params; - bool m_isApplied; QHash m_values; }; } diff --git a/src/3rdparty/phonon/mmf/audioequalizer.cpp b/src/3rdparty/phonon/mmf/audioequalizer.cpp index 28a8741..013412d 100644 --- a/src/3rdparty/phonon/mmf/audioequalizer.cpp +++ b/src/3rdparty/phonon/mmf/audioequalizer.cpp @@ -37,9 +37,10 @@ void AudioEqualizer::parameterChanged(const int pid, TRAP_IGNORE(eq()->SetBandLevelL(pid, value.toInt())); } -void AudioEqualizer::activateOn(CPlayerType *player) +bool AudioEqualizer::activateOn(CPlayerType *player) { m_effect.reset(CAudioEqualizer::NewL(*player)); + return true; } CAudioEqualizer *AudioEqualizer::eq() const diff --git a/src/3rdparty/phonon/mmf/audioequalizer.h b/src/3rdparty/phonon/mmf/audioequalizer.h index 5ef2af9..d072bf1 100644 --- a/src/3rdparty/phonon/mmf/audioequalizer.h +++ b/src/3rdparty/phonon/mmf/audioequalizer.h @@ -47,7 +47,7 @@ protected: virtual void parameterChanged(const int id, const QVariant &value); - virtual void activateOn(CPlayerType *player); + virtual bool activateOn(CPlayerType *player); private: inline CAudioEqualizer *eq() const; diff --git a/src/3rdparty/phonon/mmf/audiooutput.cpp b/src/3rdparty/phonon/mmf/audiooutput.cpp index d2e7d76..20130ad 100644 --- a/src/3rdparty/phonon/mmf/audiooutput.cpp +++ b/src/3rdparty/phonon/mmf/audiooutput.cpp @@ -20,6 +20,7 @@ along with this library. If not, see . #include "audiooutput.h" #include "defs.h" +#include "mediaobject.h" #include "utils.h" #include "volumeobserver.h" @@ -91,5 +92,10 @@ void MMF::AudioOutput::setVolumeObserver(VolumeObserver* observer) } } +bool MMF::AudioOutput::activateOnMediaObject(MediaObject *mo) +{ + setVolumeObserver(mo); + return true; +} QT_END_NAMESPACE diff --git a/src/3rdparty/phonon/mmf/audiooutput.h b/src/3rdparty/phonon/mmf/audiooutput.h index 0d3cca7..0a962a9 100644 --- a/src/3rdparty/phonon/mmf/audiooutput.h +++ b/src/3rdparty/phonon/mmf/audiooutput.h @@ -70,16 +70,16 @@ public: */ virtual bool setOutputDevice(const Phonon::AudioOutputDevice &); - /** - * Called by backend when nodes are connected. - */ - void setVolumeObserver(VolumeObserver* observer); +protected: + virtual bool activateOnMediaObject(MediaObject *mo); Q_SIGNALS: void volumeChanged(qreal volume); void audioDeviceFailed(); private: + void setVolumeObserver(VolumeObserver* observer); + qreal m_volume; // Not owned diff --git a/src/3rdparty/phonon/mmf/backend.cpp b/src/3rdparty/phonon/mmf/backend.cpp index d05b543..fe1b1a7 100644 --- a/src/3rdparty/phonon/mmf/backend.cpp +++ b/src/3rdparty/phonon/mmf/backend.cpp @@ -132,9 +132,7 @@ bool Backend::connectNodes(QObject *source, QObject *target) MediaNode *const mediaSource = static_cast(source); MediaNode *const mediaTarget = static_cast(target); - mediaSource->connectMediaNode(mediaTarget); - - return false; + return mediaSource->connectMediaNode(mediaTarget); } bool Backend::disconnectNodes(QObject *source, QObject *target) diff --git a/src/3rdparty/phonon/mmf/bassboost.cpp b/src/3rdparty/phonon/mmf/bassboost.cpp index ca9d5cc..f3db9d9 100644 --- a/src/3rdparty/phonon/mmf/bassboost.cpp +++ b/src/3rdparty/phonon/mmf/bassboost.cpp @@ -36,9 +36,10 @@ void BassBoost::parameterChanged(const int, // We should never be called, because we have no parameters. } -void BassBoost::activateOn(CPlayerType *player) +bool BassBoost::activateOn(CPlayerType *player) { m_effect.reset(CBassBoost::NewL(*player, true)); + return true; } QT_END_NAMESPACE diff --git a/src/3rdparty/phonon/mmf/bassboost.h b/src/3rdparty/phonon/mmf/bassboost.h index bf3c6c4..68ea272 100644 --- a/src/3rdparty/phonon/mmf/bassboost.h +++ b/src/3rdparty/phonon/mmf/bassboost.h @@ -45,7 +45,7 @@ protected: virtual void parameterChanged(const int id, const QVariant &value); - virtual void activateOn(CPlayerType *player); + virtual bool activateOn(CPlayerType *player); private: QScopedPointer m_bassBoost; diff --git a/src/3rdparty/phonon/mmf/mediaobject.cpp b/src/3rdparty/phonon/mmf/mediaobject.cpp index 4c7dc6d..f09b488 100644 --- a/src/3rdparty/phonon/mmf/mediaobject.cpp +++ b/src/3rdparty/phonon/mmf/mediaobject.cpp @@ -359,7 +359,6 @@ void MMF::MediaObject::volumeChanged(qreal volume) m_player->volumeChanged(volume); } - //----------------------------------------------------------------------------- // Video output //----------------------------------------------------------------------------- @@ -375,35 +374,10 @@ AbstractPlayer *MediaObject::abstractPlayer() const return m_player.data(); } -bool MediaObject::connectMediaNode(MediaNode *target) +bool MediaObject::activateOnMediaObject(MediaObject *) { - TRACE_CONTEXT(Backend::connect, EBackend); - - MediaNode::connectMediaNode(target); - - bool result = false; - - { - AudioOutput *const audioOutput = qobject_cast(target); - - if (audioOutput) { - TRACE("this 0x%08x -> audioOutput 0x%08x", this, audioOutput); - audioOutput->setVolumeObserver(this); - return true; - } - } - - { - VideoWidget *const videoWidget = qobject_cast(target); - - if (videoWidget) { - TRACE("this 0x%08x -> videoWidget 0x%08x", this, videoWidget); - this->setVideoOutput(&videoWidget->videoOutput()); - return true; - } - } - - return false; + // Guess what, we do nothing. + return true; } QT_END_NAMESPACE diff --git a/src/3rdparty/phonon/mmf/mediaobject.h b/src/3rdparty/phonon/mmf/mediaobject.h index 1f19068..409918d 100644 --- a/src/3rdparty/phonon/mmf/mediaobject.h +++ b/src/3rdparty/phonon/mmf/mediaobject.h @@ -80,15 +80,16 @@ public: // VolumeObserver void volumeChanged(qreal volume); - // MediaNode - virtual bool connectMediaNode(MediaNode *target); - /** * This class owns the AbstractPlayer, and will delete it upon * destruction. */ AbstractPlayer *abstractPlayer() const; + void setVideoOutput(VideoOutput* videoOutput); + + virtual bool activateOnMediaObject(MediaObject *); + Q_SIGNALS: void totalTimeChanged(qint64 length); void hasVideoChanged(bool hasVideo); @@ -118,7 +119,6 @@ private: static qint64 toMilliSeconds(const TTimeIntervalMicroSeconds &); private: - void setVideoOutput(VideoOutput* videoOutput); // Audio / video media type recognition bool m_recognizerOpened; diff --git a/src/3rdparty/phonon/mmf/mmf_medianode.cpp b/src/3rdparty/phonon/mmf/mmf_medianode.cpp index a210c49..54c51a0 100644 --- a/src/3rdparty/phonon/mmf/mmf_medianode.cpp +++ b/src/3rdparty/phonon/mmf/mmf_medianode.cpp @@ -16,6 +16,8 @@ along with this library. If not, see . */ +#include "mediaobject.h" + #include "mmf_medianode.h" QT_BEGIN_NAMESPACE @@ -26,6 +28,7 @@ using namespace Phonon::MMF; MMF::MediaNode::MediaNode(QObject *parent) : QObject::QObject(parent) , m_source(0) , m_target(0) + , m_isApplied(false) { } @@ -33,13 +36,15 @@ bool MMF::MediaNode::connectMediaNode(MediaNode *target) { m_target = target; m_target->setSource(this); - return true; + + return applyNodesOnMediaObject(target); } bool MMF::MediaNode::disconnectMediaNode(MediaNode *target) { Q_UNUSED(target); m_target = 0; + m_isApplied = false; return false; } @@ -58,6 +63,55 @@ MMF::MediaNode *MMF::MediaNode::target() const return m_target; } +bool MediaNode::applyNodesOnMediaObject(MediaNode *) +{ + // 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. + 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 unapplied; + MMF::MediaObject *mo = 0; + + do { + if (!current->m_isApplied) + unapplied.append(current); + + if (!mo) + mo = qobject_cast(current); + + current = current->target(); + } + while (current); + + // Now, lets activate all the objects, if we found the MediaObject. + + if (mo) { + for (int i = 0; i < unapplied.count(); ++i) { + MediaNode *const at = unapplied.at(i); + + // We don't want to apply MediaObject on itself. + if (at != mo) + at->activateOnMediaObject(mo); + } + } + + return true; +} QT_END_NAMESPACE diff --git a/src/3rdparty/phonon/mmf/mmf_medianode.h b/src/3rdparty/phonon/mmf/mmf_medianode.h index 17917aa..4616ff1 100644 --- a/src/3rdparty/phonon/mmf/mmf_medianode.h +++ b/src/3rdparty/phonon/mmf/mmf_medianode.h @@ -38,6 +38,8 @@ namespace Phonon { namespace MMF { +class MediaObject; + /** * @short Base class for all nodes in the MMF backend. * @@ -51,7 +53,8 @@ namespace MMF * * 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. + * 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. */ class MediaNode : public QObject { @@ -66,9 +69,27 @@ public: MediaNode *source() const; MediaNode *target() const; +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; + private: - MediaNode *m_source; - MediaNode *m_target; + /** + * 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; }; } } diff --git a/src/3rdparty/phonon/mmf/videowidget.cpp b/src/3rdparty/phonon/mmf/videowidget.cpp index 67e245e..ac93929 100644 --- a/src/3rdparty/phonon/mmf/videowidget.cpp +++ b/src/3rdparty/phonon/mmf/videowidget.cpp @@ -16,8 +16,10 @@ along with this library. If not, see . */ +#include "mediaobject.h" #include "utils.h" #include "videooutput.h" + #include "videowidget.h" QT_BEGIN_NAMESPACE @@ -161,6 +163,11 @@ VideoOutput& MMF::VideoWidget::videoOutput() return *static_cast(widget()); } +bool MMF::VideoWidget::activateOnMediaObject(MediaObject *mo) +{ + mo->setVideoOutput(&videoOutput()); + return true; +} QT_END_NAMESPACE diff --git a/src/3rdparty/phonon/mmf/videowidget.h b/src/3rdparty/phonon/mmf/videowidget.h index 89551b7..970f749 100644 --- a/src/3rdparty/phonon/mmf/videowidget.h +++ b/src/3rdparty/phonon/mmf/videowidget.h @@ -60,6 +60,9 @@ public: VideoOutput& videoOutput(); +protected: + virtual bool activateOnMediaObject(MediaObject *mo); + private: QScopedPointer m_widget; diff --git a/src/3rdparty/phonon/phonon/path.cpp b/src/3rdparty/phonon/phonon/path.cpp index aec8d05..ef3530c 100644 --- a/src/3rdparty/phonon/phonon/path.cpp +++ b/src/3rdparty/phonon/phonon/path.cpp @@ -310,8 +310,8 @@ bool PathPrivate::executeTransaction( const QList &disconnections, if (!transaction) return false; - QList::const_iterator it = disconnections.begin(); - for(;it != disconnections.end();++it) { + QList::const_iterator it = disconnections.constBegin(); + for(;it != disconnections.constEnd();++it) { const QObjectPair &pair = *it; if (!backend->disconnectNodes(pair.first, pair.second)) { @@ -327,8 +327,8 @@ bool PathPrivate::executeTransaction( const QList &disconnections, } } - for(it = connections.begin(); it != connections.end();++it) { - const QObjectPair &pair = *it; + for(it = connections.constBegin(); it != connections.constEnd(); ++it) { + const QObjectPair pair = *it; if (!backend->connectNodes(pair.first, pair.second)) { //Error: a connection failed QList::const_iterator it2 = connections.begin(); -- cgit v0.12