From 0089269b13244e0a906443e30f39275bb0cc01f0 Mon Sep 17 00:00:00 2001 From: Frans Englich Date: Fri, 3 Jul 2009 15:52:24 +0200 Subject: Pouring. --- src/3rdparty/phonon/mmf/audiooutput.cpp | 38 ++++++++++++- src/3rdparty/phonon/mmf/audiooutput.h | 37 +++++++++++++ src/3rdparty/phonon/mmf/backend.cpp | 16 ++++-- src/3rdparty/phonon/mmf/mediaobject.cpp | 98 +++++++++++++++++++++++++-------- src/3rdparty/phonon/mmf/mediaobject.h | 27 +++++++-- 5 files changed, 184 insertions(+), 32 deletions(-) diff --git a/src/3rdparty/phonon/mmf/audiooutput.cpp b/src/3rdparty/phonon/mmf/audiooutput.cpp index a66e079..ddc48b0 100644 --- a/src/3rdparty/phonon/mmf/audiooutput.cpp +++ b/src/3rdparty/phonon/mmf/audiooutput.cpp @@ -16,12 +16,17 @@ along with this library. If not, see . */ +#include + +#include "mediaobject.h" #include "audiooutput.h" using namespace Phonon; using namespace Phonon::MMF; -AudioOutput::AudioOutput(Backend *, QObject *parent) +AudioOutput::AudioOutput(Backend *, QObject *parent) : m_mediaObject(0) + , m_volume(0) + , m_maxVolume(-1) { setParent(parent); } @@ -31,8 +36,19 @@ qreal AudioOutput::volume() const return 0; } -void AudioOutput::setVolume(qreal) +void AudioOutput::setVolume(qreal newVolume) { + if(!m_mediaObject) + return; + + Q_ASSERT(m_mediaObject->m_player); + + if (newVolume == m_volume) + return; + + m_volume = newVolume; + m_mediaObject->m_player->SetVolume(newVolume * m_maxVolume); + emit volumeChanged(m_volume); } int AudioOutput::outputDevice() const @@ -50,3 +66,21 @@ bool AudioOutput::setOutputDevice(const Phonon::AudioOutputDevice &) return true; } +void AudioOutput::setMediaObject(MediaObject *mo) +{ + Q_ASSERT(m_mediaObject); + m_mediaObject = mo; + + Q_ASSERT(m_mediaObject->m_player); + m_maxVolume = m_mediaObject->m_player->MaxVolume(); + + TInt mmfVolume = 0; + const TInt errorCode = m_mediaObject->m_player->GetVolume(mmfVolume); + + if(errorCode == KErrNone) + return; + + m_volume = mmfVolume / m_maxVolume; + emit volumeChanged(m_volume); +} + diff --git a/src/3rdparty/phonon/mmf/audiooutput.h b/src/3rdparty/phonon/mmf/audiooutput.h index 4072756..02dd046 100644 --- a/src/3rdparty/phonon/mmf/audiooutput.h +++ b/src/3rdparty/phonon/mmf/audiooutput.h @@ -26,7 +26,26 @@ namespace Phonon namespace MMF { class Backend; + class MediaObject; + /** + * @short AudioOutputInterface42 implementation for MMF. + * + * Implements the AudioOutputInterface42 for Symbian/S60's MMF + * framework. + * + * This class has a very small role, we simply access CDrmPlayerUtility + * in MediaObject::m_player and forward everything there. + * + * \section volume Volume + * + * Phonon's concept on volume is from 0.0 to 1.0, and from 1< it does + * voltage multiplication. CDrmPlayerUtility goes from 1 to + * CDrmPlayerUtility::MaxVolume(). We apply some basic math to convert + * between the two. + * + * @author Frans Englich + */ class AudioOutput : public QObject , public AudioOutputInterface42 { @@ -37,8 +56,26 @@ namespace Phonon virtual void setVolume(qreal); virtual int outputDevice() const; + + /** + * Has no effect. + */ virtual bool setOutputDevice(int); + + /** + * Has no effect. + */ virtual bool setOutputDevice(const Phonon::AudioOutputDevice &); + + void setMediaObject(MediaObject *mo); + + Q_SIGNALS: + void volumeChanged(qreal newVolume); + + private: + MediaObject * m_mediaObject; + qreal m_volume; + TInt m_maxVolume; }; } } diff --git a/src/3rdparty/phonon/mmf/backend.cpp b/src/3rdparty/phonon/mmf/backend.cpp index 5b78158..9419fb8 100644 --- a/src/3rdparty/phonon/mmf/backend.cpp +++ b/src/3rdparty/phonon/mmf/backend.cpp @@ -77,19 +77,27 @@ bool Backend::startConnectionChange(QSet) return false; } -bool Backend::connectNodes(QObject *, QObject *) +bool Backend::connectNodes(QObject *source, QObject *target) { - return false; + MediaObject *const mo = qobject_cast(source); + AudioOutput *const ao = qobject_cast(target); + + if(!mo || !ao) + return false; + + ao->setMediaObject(mo); + + return true; } bool Backend::disconnectNodes(QObject *, QObject *) { - return false; + return true; } bool Backend::endConnectionChange(QSet) { - return false; + return true; } QStringList Backend::availableMimeTypes() const diff --git a/src/3rdparty/phonon/mmf/mediaobject.cpp b/src/3rdparty/phonon/mmf/mediaobject.cpp index 2db56d6..79b7558 100644 --- a/src/3rdparty/phonon/mmf/mediaobject.cpp +++ b/src/3rdparty/phonon/mmf/mediaobject.cpp @@ -16,6 +16,9 @@ along with this library. If not, see . */ +#include +#include + #include "mediaobject.h" using namespace Phonon; @@ -27,6 +30,8 @@ MediaObject::MediaObject(QObject *parent) : m_player(0) { Q_UNUSED(parent); m_player = CDrmPlayerUtility::NewL(*this, 0, EMdaPriorityPreferenceNone); + + m_player->RegisterForAudioLoadingNotification(*this); } MediaObject::~MediaObject() @@ -36,19 +41,19 @@ MediaObject::~MediaObject() void MediaObject::play() { - m_state = PlayingState; + transitTo(PlayingState); m_player->Play(); } void MediaObject::pause() { - m_state = PausedState; + transitTo(PausedState); m_player->Pause(); } void MediaObject::stop() { - m_state = StoppedState; + transitTo(StoppedState); m_player->Stop(); } @@ -85,17 +90,12 @@ qint64 MediaObject::currentTime() const if(retcode == KErrNone) return toMilliSeconds(m_player->Duration()); else { - m_state = ErrorState; - m_error = NormalError; + // TODO Should we enter/emit error state? Tricky + // since we're in a const function. return -1; } } -Phonon::State MediaObject::state() const -{ - return m_state; -} - QString MediaObject::errorString() const { return QString(); @@ -123,22 +123,47 @@ qint64 MediaObject::totalTime() const MediaSource MediaObject::source() const { - return MediaSource(); + return m_mediaSource; } void MediaObject::setSource(const MediaSource &source) { stop(); - m_state = LoadingState; - - Q_UNUSED(source); - // TODO + m_mediaSource = source; + + switch(m_mediaSource.type()) + { + case MediaSource::LocalFile: + { + const QHBufC filename(source.fileName()); + m_player->OpenFileL(*filename); + break; + } + case MediaSource::Url: + { + const QHBufC filename(source.url().toString()); + m_player->OpenUrlL(*filename); + break; + } + case MediaSource::Invalid: + /* Fallthrough. */ + case MediaSource::Disc: + /* Fallthrough. */ + case MediaSource::Stream: + /* Fallthrough. */ + case MediaSource::Empty: + { + transitTo(ErrorState); + return; + } + } - emit totalTimeChanged(); + transitTo(LoadingState); } void MediaObject::setNextSource(const MediaSource &source) { + m_nextSource = source; Q_UNUSED(source); } @@ -162,23 +187,52 @@ void MediaObject::setTransitionTime(qint32) void MediaObject::MaloLoadingComplete() { - m_state = StoppedState; + transitTo(StoppedState); } void MediaObject::MaloLoadingStarted() { - m_state = LoadingState; + transitTo(LoadingState); } void MediaObject::MdapcInitComplete(TInt aError, - const TTimeIntervalMicroSeconds &aDuration) + const TTimeIntervalMicroSeconds &) { - Q_UNUSED(aError); - Q_UNUSED(aDuration); + if(aError == KErrNone) { + m_error = NormalError; + m_state = ErrorState; + } + + emit totalTimeChanged(); + transitTo(StoppedState); } void MediaObject::MdapcPlayComplete(TInt aError) { - Q_UNUSED(aError); + if(aError == KErrNone) { + if(m_nextSource.type() == MediaSource::Empty) { + emit finished(); + } else { + setSource(m_nextSource); + m_nextSource = MediaSource(); + } + + transitTo(StoppedState); + } + else { + m_error = NormalError; + transitTo(ErrorState); + } +} + +void MediaObject::transitTo(Phonon::State newState) +{ + emit stateChanged(m_state, newState); + m_state = newState; +} + +Phonon::State MediaObject::state() const +{ + return m_state; } diff --git a/src/3rdparty/phonon/mmf/mediaobject.h b/src/3rdparty/phonon/mmf/mediaobject.h index 80a774d..1512919 100644 --- a/src/3rdparty/phonon/mmf/mediaobject.h +++ b/src/3rdparty/phonon/mmf/mediaobject.h @@ -31,9 +31,12 @@ namespace Phonon { namespace MMF { + class AudioOutput; + class MediaObject : public QObject , public MediaObjectInterface , public MDrmAudioPlayerCallback + , public MAudioLoadingObserver { Q_OBJECT Q_INTERFACES(Phonon::MediaObjectInterface) @@ -64,22 +67,38 @@ namespace Phonon // MAudioLoadingObserver virtual void MaloLoadingComplete(); virtual void MaloLoadingStarted(); - + // MDrmAudioPlayerCallback virtual void MdapcInitComplete(TInt aError, - const TTimeIntervalMicroSeconds &aDuration); + const TTimeIntervalMicroSeconds &aDuration); virtual void MdapcPlayComplete(TInt aError); Q_SIGNALS: void totalTimeChanged(); + void stateChanged(Phonon::State oldState, + Phonon::State newState); + + void finished(); private: + friend class AudioOutput; static inline qint64 toMilliSeconds(const TTimeIntervalMicroSeconds &); static inline TTimeIntervalMicroSeconds toMicroSeconds(qint64 ms); + /** + * Changes state() to \a newState, and emits stateChanged(). + */ + inline void transitTo(Phonon::State newState); + CDrmPlayerUtility * m_player; - mutable ErrorType m_error; - mutable State m_state; + ErrorType m_error; + + /** + * Never update this state by assigning to it. Call transitTo(). + */ + State m_state; + MediaSource m_mediaSource; + MediaSource m_nextSource; }; } } -- cgit v0.12