summaryrefslogtreecommitdiffstats
path: root/doc/src/snippets/code/src_network_kernel_qhostaddress.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'doc/src/snippets/code/src_network_kernel_qhostaddress.cpp')
0 files changed, 0 insertions, 0 deletions
TNESS 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 . + +*/ + +#ifndef PHONON_MMF_AUDIOOUTPUT_H +#define PHONON_MMF_AUDIOOUTPUT_H + +#include + +namespace Phonon +{ + namespace MMF + { + class Backend; + + class AudioOutput : public QObject + , public AudioOutputInterface42 + { + Q_OBJECT + public: + AudioOutput(Backend *backend, QObject *parent); + virtual qreal volume() const; + virtual void setVolume(qreal); + + virtual int outputDevice() const; + virtual bool setOutputDevice(int); + virtual bool setOutputDevice(const Phonon::AudioOutputDevice &); + }; + } +} + +#endif diff --git a/src/3rdparty/phonon/mmf/backend.cpp b/src/3rdparty/phonon/mmf/backend.cpp new file mode 100644 index 0000000..5b78158 --- /dev/null +++ b/src/3rdparty/phonon/mmf/backend.cpp @@ -0,0 +1,101 @@ +/* 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 . + +*/ + +#include +#include + +#include "backend.h" +#include "audiooutput.h" +#include "mediaobject.h" + +using namespace Phonon; +using namespace Phonon::MMF; + +Backend::Backend(QObject *parent) +{ + setParent(parent); + + setProperty("identifier", QLatin1String("mmf")); + setProperty("backendName", QLatin1String("MMF")); + setProperty("backendComment", QLatin1String("MMF Backend")); + setProperty("backendVersion", QLatin1String("0.1")); + setProperty("backendWebsite", QLatin1String("http://www.qtsoftware.com/")); +} + +QObject *Backend::createObject(BackendInterface::Class c, QObject *parent, const QList &) +{ + switch(c) + { + case AudioOutputClass: + return new AudioOutput(this, parent); + case MediaObjectClass: + return new MediaObject(parent); + case VolumeFaderEffectClass: + /* Fallthrough. */ + case VisualizationClass: + /* Fallthrough. */ + case VideoDataOutputClass: + /* Fallthrough. */ + case EffectClass: + /* Fallthrough. */ + case VideoWidgetClass: + return 0; + } + + Q_ASSERT_X(false, Q_FUNC_INFO, + "This line should never be reached."); + return 0; +} + +QList Backend::objectDescriptionIndexes(ObjectDescriptionType) const +{ + return QList(); +} + +QHash Backend::objectDescriptionProperties(ObjectDescriptionType, int) const +{ + return QHash(); +} + +bool Backend::startConnectionChange(QSet) +{ + return false; +} + +bool Backend::connectNodes(QObject *, QObject *) +{ + return false; +} + +bool Backend::disconnectNodes(QObject *, QObject *) +{ + return false; +} + +bool Backend::endConnectionChange(QSet) +{ + return false; +} + +QStringList Backend::availableMimeTypes() const +{ + return QStringList(); +} + +Q_EXPORT_PLUGIN2(phonon_mmf, Phonon::MMF::Backend); + diff --git a/src/3rdparty/phonon/mmf/backend.h b/src/3rdparty/phonon/mmf/backend.h new file mode 100644 index 0000000..cb03859 --- /dev/null +++ b/src/3rdparty/phonon/mmf/backend.h @@ -0,0 +1,49 @@ +/* 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 . + +*/ + +#ifndef PHONON_MMF_BACKEND_H +#define PHONON_MMF_BACKEND_H + +#include +#include + +namespace Phonon +{ + namespace MMF + { + class Backend : public QObject + , public BackendInterface + { + Q_OBJECT + Q_INTERFACES(Phonon::BackendInterface) + public: + Backend(QObject *parent = 0); + + virtual QObject *createObject(BackendInterface::Class c, QObject *parent, const QList &args); + virtual QList objectDescriptionIndexes(ObjectDescriptionType type) const; + virtual QHash objectDescriptionProperties(ObjectDescriptionType type, int index) const; + virtual bool startConnectionChange(QSet); + virtual bool connectNodes(QObject *, QObject *); + virtual bool disconnectNodes(QObject *, QObject *); + virtual bool endConnectionChange(QSet); + virtual QStringList availableMimeTypes() const; + }; + } +} + +#endif diff --git a/src/3rdparty/phonon/mmf/mediaobject.cpp b/src/3rdparty/phonon/mmf/mediaobject.cpp new file mode 100644 index 0000000..2db56d6 --- /dev/null +++ b/src/3rdparty/phonon/mmf/mediaobject.cpp @@ -0,0 +1,184 @@ +/* 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 . + +*/ + +#include "mediaobject.h" + +using namespace Phonon; +using namespace Phonon::MMF; + +MediaObject::MediaObject(QObject *parent) : m_player(0) + , m_error(NoError) + , m_state(StoppedState) +{ + Q_UNUSED(parent); + m_player = CDrmPlayerUtility::NewL(*this, 0, EMdaPriorityPreferenceNone); +} + +MediaObject::~MediaObject() +{ + delete m_player; +} + +void MediaObject::play() +{ + m_state = PlayingState; + m_player->Play(); +} + +void MediaObject::pause() +{ + m_state = PausedState; + m_player->Pause(); +} + +void MediaObject::stop() +{ + m_state = StoppedState; + m_player->Stop(); +} + +void MediaObject::seek(qint64 milliseconds) +{ + m_player->SetPosition(toMicroSeconds(milliseconds)); +} + +qint32 MediaObject::tickInterval() const +{ + return 0; +} + +void MediaObject::setTickInterval(qint32 interval) +{ + Q_UNUSED(interval); +} + +bool MediaObject::hasVideo() const +{ + return false; +} + +bool MediaObject::isSeekable() const +{ + return false; +} + +qint64 MediaObject::currentTime() const +{ + TTimeIntervalMicroSeconds mss; + const TInt retcode = m_player->GetPosition(mss); + + if(retcode == KErrNone) + return toMilliSeconds(m_player->Duration()); + else { + m_state = ErrorState; + m_error = NormalError; + return -1; + } +} + +Phonon::State MediaObject::state() const +{ + return m_state; +} + +QString MediaObject::errorString() const +{ + return QString(); +} + +Phonon::ErrorType MediaObject::errorType() const +{ + return m_error; +} + +qint64 MediaObject::toMilliSeconds(const TTimeIntervalMicroSeconds &in) +{ + return in.Int64() / 1000; +} + +TTimeIntervalMicroSeconds MediaObject::toMicroSeconds(qint64 ms) +{ + return TTimeIntervalMicroSeconds(TInt64(ms)); +} + +qint64 MediaObject::totalTime() const +{ + return toMilliSeconds(m_player->Duration()); +} + +MediaSource MediaObject::source() const +{ + return MediaSource(); +} + +void MediaObject::setSource(const MediaSource &source) +{ + stop(); + m_state = LoadingState; + + Q_UNUSED(source); + // TODO + + emit totalTimeChanged(); +} + +void MediaObject::setNextSource(const MediaSource &source) +{ + Q_UNUSED(source); +} + +qint32 MediaObject::prefinishMark() const +{ + return 0; +} + +void MediaObject::setPrefinishMark(qint32) +{ +} + +qint32 MediaObject::transitionTime() const +{ + return 0; +} + +void MediaObject::setTransitionTime(qint32) +{ +} + +void MediaObject::MaloLoadingComplete() +{ + m_state = StoppedState; +} + +void MediaObject::MaloLoadingStarted() +{ + m_state = LoadingState; +} + +void MediaObject::MdapcInitComplete(TInt aError, + const TTimeIntervalMicroSeconds &aDuration) +{ + Q_UNUSED(aError); + Q_UNUSED(aDuration); +} + +void MediaObject::MdapcPlayComplete(TInt aError) +{ + Q_UNUSED(aError); +} + diff --git a/src/3rdparty/phonon/mmf/mediaobject.h b/src/3rdparty/phonon/mmf/mediaobject.h new file mode 100644 index 0000000..80a774d --- /dev/null +++ b/src/3rdparty/phonon/mmf/mediaobject.h @@ -0,0 +1,87 @@ +/* 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 . + +*/ + +#ifndef PHONON_MMF_MEDIAOBJECT_H +#define PHONON_MMF_MEDIAOBJECT_H + +#include + +#include +#include + +class CDrmPlayerUtility; +class TTimeIntervalMicroSeconds; + +namespace Phonon +{ + namespace MMF + { + class MediaObject : public QObject + , public MediaObjectInterface + , public MDrmAudioPlayerCallback + { + Q_OBJECT + Q_INTERFACES(Phonon::MediaObjectInterface) + public: + MediaObject(QObject *parent); + virtual ~MediaObject(); + virtual void play(); + virtual void pause(); + virtual void stop(); + virtual void seek(qint64 milliseconds); + virtual qint32 tickInterval() const; + virtual void setTickInterval(qint32 interval); + virtual bool hasVideo() const; + virtual bool isSeekable() const; + virtual qint64 currentTime() const; + virtual Phonon::State state() const; + virtual QString errorString() const; + virtual Phonon::ErrorType errorType() const; + virtual qint64 totalTime() const; + virtual MediaSource source() const; + virtual void setSource(const MediaSource &); + virtual void setNextSource(const MediaSource &source); + virtual qint32 prefinishMark() const; + virtual void setPrefinishMark(qint32); + virtual qint32 transitionTime() const; + virtual void setTransitionTime(qint32); + + // MAudioLoadingObserver + virtual void MaloLoadingComplete(); + virtual void MaloLoadingStarted(); + + // MDrmAudioPlayerCallback + virtual void MdapcInitComplete(TInt aError, + const TTimeIntervalMicroSeconds &aDuration); + virtual void MdapcPlayComplete(TInt aError); + + Q_SIGNALS: + void totalTimeChanged(); + + private: + static inline qint64 toMilliSeconds(const TTimeIntervalMicroSeconds &); + static inline TTimeIntervalMicroSeconds toMicroSeconds(qint64 ms); + + CDrmPlayerUtility * m_player; + mutable ErrorType m_error; + mutable State m_state; + }; + } +} + +#endif diff --git a/src/plugins/phonon/mmf/mmf.pro b/src/plugins/phonon/mmf/mmf.pro index 0c4bff7..381f119 100644 --- a/src/plugins/phonon/mmf/mmf.pro +++ b/src/plugins/phonon/mmf/mmf.pro @@ -2,53 +2,23 @@ DESTDIR = $$QT_BUILD_TREE/plugins/phonon_backend QT += phonon TARGET = phonon_mmf PHONON_MMF_DIR = $$QT_SOURCE_TREE/src/3rdparty/phonon/mmf +LIBS += -lDrmAudioPlayUtility.lib -# Input -HEADERS += \ - $$PHONON_MMF_DIR/abstractvideorenderer.h \ - $$PHONON_MMF_DIR/audiooutput.h \ - $$PHONON_MMF_DIR/backend.h \ - $$PHONON_MMF_DIR/backendnode.h \ - $$PHONON_MMF_DIR/effect.h \ - $$PHONON_MMF_DIR/fakesource.h \ - $$PHONON_MMF_DIR/iodevicereader.h \ - $$PHONON_MMF_DIR/mediagraph.h \ - $$PHONON_MMF_DIR/mediaobject.h \ - $$PHONON_MMF_DIR/videowidget.h \ - $$PHONON_MMF_DIR/videorenderer_soft.h \ - $$PHONON_MMF_DIR/videorenderer_vmr9.h \ - $$PHONON_MMF_DIR/volumeeffect.h \ - $$PHONON_MMF_DIR/qbasefilter.h \ - $$PHONON_MMF_DIR/qpin.h \ - $$PHONON_MMF_DIR/qasyncreader.h \ - $$PHONON_MMF_DIR/qaudiocdreader.h \ - $$PHONON_MMF_DIR/qmeminputpin.h \ - $$PHONON_MMF_DIR/compointer.h \ - $$PHONON_MMF_DIR/phononds9_namespace.h +HEADERS += \ + $$PHONON_MMF_DIR/audiooutput.h \ + $$PHONON_MMF_DIR/backend.h \ + $$PHONON_MMF_DIR/mediaobject.h - -SOURCES += \ - $$PHONON_MMF_DIR/abstractvideorenderer.cpp \ +SOURCES += \ $$PHONON_MMF_DIR/audiooutput.cpp \ - $$PHONON_MMF_DIR/backend.cpp \ - $$PHONON_MMF_DIR/backendnode.cpp \ - $$PHONON_MMF_DIR/effect.cpp \ - $$PHONON_MMF_DIR/fakesource.cpp \ - $$PHONON_MMF_DIR/iodevicereader.cpp \ - $$PHONON_MMF_DIR/mediagraph.cpp \ - $$PHONON_MMF_DIR/mediaobject.cpp \ - $$PHONON_MMF_DIR/videowidget.cpp \ - $$PHONON_MMF_DIR/videorenderer_soft.cpp \ - $$PHONON_MMF_DIR/videorenderer_vmr9.cpp \ - $$PHONON_MMF_DIR/volumeeffect.cpp \ - $$PHONON_MMF_DIR/qbasefilter.cpp \ - $$PHONON_MMF_DIR/qpin.cpp \ - $$PHONON_MMF_DIR/qasyncreader.cpp \ - $$PHONON_MMF_DIR/qaudiocdreader.cpp \ - $$PHONON_MMF_DIR/qmeminputpin.cpp - + $$PHONON_MMF_DIR/backend.cpp \ + $$PHONON_MMF_DIR/mediaobject.cpp target.path = $$[QT_INSTALL_PLUGINS]/phonon_backend INSTALLS += target include(../../qpluginbase.pri) + +# In the internal 5th SDK, DrmAudioSamplePlayer.h is placed in this folder, as +# opposed to the public, where it is placed in epoc32/include. +INCLUDEPATH *= /epoc32/include/osextensions diff --git a/src/plugins/phonon/phonon.pro b/src/plugins/phonon/phonon.pro index e43a4c2..814a062 100644 --- a/src/plugins/phonon/phonon.pro +++ b/src/plugins/phonon/phonon.pro @@ -7,3 +7,4 @@ mac:contains(QT_CONFIG, phonon-backend): SUBDIRS *= qt7 win32:!wince*:contains(QT_CONFIG, phonon-backend): SUBDIRS *= ds9 wince*:contains(QT_CONFIG, phonon-backend): SUBDIRS *= waveout wince*:contains(QT_CONFIG, directshow): SUBDIRS *= ds9 +symbian:contains(QT_CONFIG, phonon-backend): SUBDIRS *= mmf -- cgit v0.12 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 From 0e54042f2d339ecf85a89f8603317c32da265a90 Mon Sep 17 00:00:00 2001 From: Frans Englich Date: Fri, 3 Jul 2009 16:33:19 +0200 Subject: Load Helix backend before loading the Phonon backend. --- src/3rdparty/phonon/phonon/factory.cpp | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/3rdparty/phonon/phonon/factory.cpp b/src/3rdparty/phonon/phonon/factory.cpp index 43c45ee..1026bb3 100644 --- a/src/3rdparty/phonon/phonon/factory.cpp +++ b/src/3rdparty/phonon/phonon/factory.cpp @@ -131,7 +131,23 @@ bool FactoryPrivate::createBackend() pDebug() << Q_FUNC_INFO << dir.absolutePath() << "does not exist"; continue; } - foreach (const QString &pluginName, dir.entryList(QDir::Files)) { + + QStringList plugins(dir.entryList(QDir::Files)); + +#ifdef Q_OS_SYMBIAN + /* On Symbian OS we might have two plugins, one which uses Symbian + * MMF framework("mmf"), and one which uses Real Networks's + * Helix("hxphonon"). We prefer the latter because it's more + * sophisticated, so we make sure the Helix backend is attempted + * to be loaded first, and the MMF backend is used for backup. */ + { + const int helix = plugins.indexof(QLatin1String("hxphonon")); + if (helix != -1) + plugins.move(helix, 0); + } +#endif + + foreach (const QString &pluginName, plugins) { QPluginLoader pluginLoader(libPath + pluginName); if (!pluginLoader.load()) { pDebug() << Q_FUNC_INFO << " load failed:" -- cgit v0.12 From 7ead0ff857d8f164e9cfa3f756a1b234a76eedc6 Mon Sep 17 00:00:00 2001 From: Frans Englich Date: Fri, 3 Jul 2009 16:38:27 +0200 Subject: Adjust comment field. --- src/3rdparty/phonon/mmf/backend.cpp | 2 +- src/3rdparty/phonon/phonon/factory.cpp | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/3rdparty/phonon/mmf/backend.cpp b/src/3rdparty/phonon/mmf/backend.cpp index 9419fb8..86d329b 100644 --- a/src/3rdparty/phonon/mmf/backend.cpp +++ b/src/3rdparty/phonon/mmf/backend.cpp @@ -32,7 +32,7 @@ Backend::Backend(QObject *parent) setProperty("identifier", QLatin1String("mmf")); setProperty("backendName", QLatin1String("MMF")); - setProperty("backendComment", QLatin1String("MMF Backend")); + setProperty("backendComment", QLatin1String("Backend using Nokia's S60 Multimedia Framework Architecture (MMF).")); setProperty("backendVersion", QLatin1String("0.1")); setProperty("backendWebsite", QLatin1String("http://www.qtsoftware.com/")); } diff --git a/src/3rdparty/phonon/phonon/factory.cpp b/src/3rdparty/phonon/phonon/factory.cpp index 1026bb3..34d04fa 100644 --- a/src/3rdparty/phonon/phonon/factory.cpp +++ b/src/3rdparty/phonon/phonon/factory.cpp @@ -141,9 +141,15 @@ bool FactoryPrivate::createBackend() * sophisticated, so we make sure the Helix backend is attempted * to be loaded first, and the MMF backend is used for backup. */ { - const int helix = plugins.indexof(QLatin1String("hxphonon")); + const int helix = plugins.indexOf(QLatin1String("hxphonon")); if (helix != -1) plugins.move(helix, 0); + + // Code for debugging the MMF backend. + if(helix != -1) { + qDebug() << "Found helix, and removed it from the lookup list."; + plugins.removeAll(QLatin1String("hxphonon")); + } } #endif -- cgit v0.12 From 975af6c3c81788e39422c55f67ffabfebd31d9be Mon Sep 17 00:00:00 2001 From: Frans Englich Date: Mon, 13 Jul 2009 11:44:55 +0200 Subject: Build fixes, debug code. --- src/3rdparty/phonon/mmf/audiooutput.cpp | 18 +++++----- src/3rdparty/phonon/mmf/mediaobject.cpp | 64 ++++++++++++++++----------------- src/3rdparty/phonon/mmf/mediaobject.h | 10 ++++++ src/3rdparty/phonon/phonon/factory.cpp | 13 +++---- 4 files changed, 58 insertions(+), 47 deletions(-) diff --git a/src/3rdparty/phonon/mmf/audiooutput.cpp b/src/3rdparty/phonon/mmf/audiooutput.cpp index ddc48b0..9d1ff02 100644 --- a/src/3rdparty/phonon/mmf/audiooutput.cpp +++ b/src/3rdparty/phonon/mmf/audiooutput.cpp @@ -24,19 +24,19 @@ along with this library. If not, see . using namespace Phonon; using namespace Phonon::MMF; -AudioOutput::AudioOutput(Backend *, QObject *parent) : m_mediaObject(0) - , m_volume(0) - , m_maxVolume(-1) +MMF::AudioOutput::AudioOutput(Backend *, QObject *parent) : m_mediaObject(0) + , m_volume(0) + , m_maxVolume(-1) { setParent(parent); } -qreal AudioOutput::volume() const +qreal MMF::AudioOutput::volume() const { return 0; } -void AudioOutput::setVolume(qreal newVolume) +void MMF::AudioOutput::setVolume(qreal newVolume) { if(!m_mediaObject) return; @@ -51,22 +51,22 @@ void AudioOutput::setVolume(qreal newVolume) emit volumeChanged(m_volume); } -int AudioOutput::outputDevice() const +int MMF::AudioOutput::outputDevice() const { return 0; } -bool AudioOutput::setOutputDevice(int) +bool MMF::AudioOutput::setOutputDevice(int) { return true; } -bool AudioOutput::setOutputDevice(const Phonon::AudioOutputDevice &) +bool MMF::AudioOutput::setOutputDevice(const Phonon::AudioOutputDevice &) { return true; } -void AudioOutput::setMediaObject(MediaObject *mo) +void MMF::AudioOutput::setMediaObject(MediaObject *mo) { Q_ASSERT(m_mediaObject); m_mediaObject = mo; diff --git a/src/3rdparty/phonon/mmf/mediaobject.cpp b/src/3rdparty/phonon/mmf/mediaobject.cpp index 79b7558..605fe24 100644 --- a/src/3rdparty/phonon/mmf/mediaobject.cpp +++ b/src/3rdparty/phonon/mmf/mediaobject.cpp @@ -24,9 +24,9 @@ along with this library. If not, see . using namespace Phonon; using namespace Phonon::MMF; -MediaObject::MediaObject(QObject *parent) : m_player(0) - , m_error(NoError) - , m_state(StoppedState) +MMF::MediaObject::MediaObject(QObject *parent) : m_player(0) + , m_error(NoError) + , m_state(StoppedState) { Q_UNUSED(parent); m_player = CDrmPlayerUtility::NewL(*this, 0, EMdaPriorityPreferenceNone); @@ -34,55 +34,55 @@ MediaObject::MediaObject(QObject *parent) : m_player(0) m_player->RegisterForAudioLoadingNotification(*this); } -MediaObject::~MediaObject() +MMF::MediaObject::~MediaObject() { delete m_player; } -void MediaObject::play() +void MMF::MediaObject::play() { transitTo(PlayingState); m_player->Play(); } -void MediaObject::pause() +void MMF::MediaObject::pause() { transitTo(PausedState); m_player->Pause(); } -void MediaObject::stop() +void MMF::MediaObject::stop() { transitTo(StoppedState); m_player->Stop(); } -void MediaObject::seek(qint64 milliseconds) +void MMF::MediaObject::seek(qint64 milliseconds) { m_player->SetPosition(toMicroSeconds(milliseconds)); } -qint32 MediaObject::tickInterval() const +qint32 MMF::MediaObject::tickInterval() const { return 0; } -void MediaObject::setTickInterval(qint32 interval) +void MMF::MediaObject::setTickInterval(qint32 interval) { Q_UNUSED(interval); } -bool MediaObject::hasVideo() const +bool MMF::MediaObject::hasVideo() const { return false; } -bool MediaObject::isSeekable() const +bool MMF::MediaObject::isSeekable() const { return false; } -qint64 MediaObject::currentTime() const +qint64 MMF::MediaObject::currentTime() const { TTimeIntervalMicroSeconds mss; const TInt retcode = m_player->GetPosition(mss); @@ -96,37 +96,37 @@ qint64 MediaObject::currentTime() const } } -QString MediaObject::errorString() const +QString MMF::MediaObject::errorString() const { return QString(); } -Phonon::ErrorType MediaObject::errorType() const +Phonon::ErrorType MMF::MediaObject::errorType() const { return m_error; } -qint64 MediaObject::toMilliSeconds(const TTimeIntervalMicroSeconds &in) +qint64 MMF::MediaObject::toMilliSeconds(const TTimeIntervalMicroSeconds &in) { return in.Int64() / 1000; } -TTimeIntervalMicroSeconds MediaObject::toMicroSeconds(qint64 ms) +TTimeIntervalMicroSeconds MMF::MediaObject::toMicroSeconds(qint64 ms) { return TTimeIntervalMicroSeconds(TInt64(ms)); } -qint64 MediaObject::totalTime() const +qint64 MMF::MediaObject::totalTime() const { return toMilliSeconds(m_player->Duration()); } -MediaSource MediaObject::source() const +MediaSource MMF::MediaObject::source() const { return m_mediaSource; } -void MediaObject::setSource(const MediaSource &source) +void MMF::MediaObject::setSource(const MediaSource &source) { stop(); m_mediaSource = source; @@ -161,42 +161,42 @@ void MediaObject::setSource(const MediaSource &source) transitTo(LoadingState); } -void MediaObject::setNextSource(const MediaSource &source) +void MMF::MediaObject::setNextSource(const MediaSource &source) { m_nextSource = source; Q_UNUSED(source); } -qint32 MediaObject::prefinishMark() const +qint32 MMF::MediaObject::prefinishMark() const { return 0; } -void MediaObject::setPrefinishMark(qint32) +void MMF::MediaObject::setPrefinishMark(qint32) { } -qint32 MediaObject::transitionTime() const +qint32 MMF::MediaObject::transitionTime() const { return 0; } -void MediaObject::setTransitionTime(qint32) +void MMF::MediaObject::setTransitionTime(qint32) { } -void MediaObject::MaloLoadingComplete() +void MMF::MediaObject::MaloLoadingComplete() { transitTo(StoppedState); } -void MediaObject::MaloLoadingStarted() +void MMF::MediaObject::MaloLoadingStarted() { transitTo(LoadingState); } -void MediaObject::MdapcInitComplete(TInt aError, - const TTimeIntervalMicroSeconds &) +void MMF::MediaObject::MdapcInitComplete(TInt aError, + const TTimeIntervalMicroSeconds &) { if(aError == KErrNone) { m_error = NormalError; @@ -207,7 +207,7 @@ void MediaObject::MdapcInitComplete(TInt aError, transitTo(StoppedState); } -void MediaObject::MdapcPlayComplete(TInt aError) +void MMF::MediaObject::MdapcPlayComplete(TInt aError) { if(aError == KErrNone) { if(m_nextSource.type() == MediaSource::Empty) { @@ -225,13 +225,13 @@ void MediaObject::MdapcPlayComplete(TInt aError) } } -void MediaObject::transitTo(Phonon::State newState) +void MMF::MediaObject::transitTo(Phonon::State newState) { emit stateChanged(m_state, newState); m_state = newState; } -Phonon::State MediaObject::state() const +Phonon::State MMF::MediaObject::state() const { return m_state; } diff --git a/src/3rdparty/phonon/mmf/mediaobject.h b/src/3rdparty/phonon/mmf/mediaobject.h index 1512919..3afa3b4 100644 --- a/src/3rdparty/phonon/mmf/mediaobject.h +++ b/src/3rdparty/phonon/mmf/mediaobject.h @@ -20,6 +20,7 @@ along with this library. If not, see . #define PHONON_MMF_MEDIAOBJECT_H #include +#include #include #include @@ -33,16 +34,25 @@ namespace Phonon { class AudioOutput; + /** + * + * See + * How to + * play a video file using CVideoPlayerUtility + */ class MediaObject : public QObject , public MediaObjectInterface , public MDrmAudioPlayerCallback , public MAudioLoadingObserver + //, public MVideoPlayerUtilityObserver { Q_OBJECT Q_INTERFACES(Phonon::MediaObjectInterface) public: MediaObject(QObject *parent); virtual ~MediaObject(); + + // MediaObjectInterface virtual void play(); virtual void pause(); virtual void stop(); diff --git a/src/3rdparty/phonon/phonon/factory.cpp b/src/3rdparty/phonon/phonon/factory.cpp index 34d04fa..d828756 100644 --- a/src/3rdparty/phonon/phonon/factory.cpp +++ b/src/3rdparty/phonon/phonon/factory.cpp @@ -125,6 +125,7 @@ bool FactoryPrivate::createBackend() // (finding the first loadable backend). const QLatin1String suffix("/phonon_backend/"); foreach (QString libPath, QCoreApplication::libraryPaths()) { + qDebug() << Q_FUNC_INFO << "Lookinng in" << libPath; libPath += suffix; const QDir dir(libPath); if (!dir.exists()) { @@ -136,18 +137,18 @@ bool FactoryPrivate::createBackend() #ifdef Q_OS_SYMBIAN /* On Symbian OS we might have two plugins, one which uses Symbian - * MMF framework("mmf"), and one which uses Real Networks's + * MMF framework("phonon_mmf"), and one which uses Real Networks's * Helix("hxphonon"). We prefer the latter because it's more * sophisticated, so we make sure the Helix backend is attempted * to be loaded first, and the MMF backend is used for backup. */ { - const int helix = plugins.indexOf(QLatin1String("hxphonon")); - if (helix != -1) - plugins.move(helix, 0); + const int hxphonon = plugins.indexOf(QLatin1String("hxphonon")); + if (hxphonon != -1) + plugins.move(hxphonon, 0); // Code for debugging the MMF backend. - if(helix != -1) { - qDebug() << "Found helix, and removed it from the lookup list."; + if(hxphonon != -1) { + qDebug() << "Found hxphonon backend and removed it from the lookup list."; plugins.removeAll(QLatin1String("hxphonon")); } } -- cgit v0.12 From 17c74f4f49f5cb7c62dc4d2300293f2e93b16a90 Mon Sep 17 00:00:00 2001 From: Frans Englich Date: Sat, 18 Jul 2009 06:02:32 +0200 Subject: Work. --- src/3rdparty/phonon/mmf/backend.cpp | 3 ++- src/3rdparty/phonon/mmf/backend.h | 3 +++ src/3rdparty/phonon/mmf/mediaobject.h | 6 +++++- src/plugins/phonon/mmf/mmf.pro | 10 +++++++++- 4 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/3rdparty/phonon/mmf/backend.cpp b/src/3rdparty/phonon/mmf/backend.cpp index 86d329b..4324409 100644 --- a/src/3rdparty/phonon/mmf/backend.cpp +++ b/src/3rdparty/phonon/mmf/backend.cpp @@ -28,9 +28,10 @@ using namespace Phonon::MMF; Backend::Backend(QObject *parent) { + qDebug() << Q_FUNC_INFO; setParent(parent); - setProperty("identifier", QLatin1String("mmf")); + setProperty("identifier", QLatin1String("phonon_mmf")); setProperty("backendName", QLatin1String("MMF")); setProperty("backendComment", QLatin1String("Backend using Nokia's S60 Multimedia Framework Architecture (MMF).")); setProperty("backendVersion", QLatin1String("0.1")); diff --git a/src/3rdparty/phonon/mmf/backend.h b/src/3rdparty/phonon/mmf/backend.h index cb03859..4fff204 100644 --- a/src/3rdparty/phonon/mmf/backend.h +++ b/src/3rdparty/phonon/mmf/backend.h @@ -42,6 +42,9 @@ namespace Phonon virtual bool disconnectNodes(QObject *, QObject *); virtual bool endConnectionChange(QSet); virtual QStringList availableMimeTypes() const; + + Q_SIGNALS: + void objectDescriptionChanged(ObjectDescriptionType); }; } } diff --git a/src/3rdparty/phonon/mmf/mediaobject.h b/src/3rdparty/phonon/mmf/mediaobject.h index 3afa3b4..207cb91 100644 --- a/src/3rdparty/phonon/mmf/mediaobject.h +++ b/src/3rdparty/phonon/mmf/mediaobject.h @@ -19,8 +19,11 @@ along with this library. If not, see . #ifndef PHONON_MMF_MEDIAOBJECT_H #define PHONON_MMF_MEDIAOBJECT_H +/* We use the extra qualification include/ to avoid picking up the include + * Phonon has. */ +#include + #include -#include #include #include @@ -44,6 +47,7 @@ namespace Phonon , public MediaObjectInterface , public MDrmAudioPlayerCallback , public MAudioLoadingObserver + , public MVideoLoadingObserver //, public MVideoPlayerUtilityObserver { Q_OBJECT diff --git a/src/plugins/phonon/mmf/mmf.pro b/src/plugins/phonon/mmf/mmf.pro index 381f119..1a1d435 100644 --- a/src/plugins/phonon/mmf/mmf.pro +++ b/src/plugins/phonon/mmf/mmf.pro @@ -2,7 +2,7 @@ DESTDIR = $$QT_BUILD_TREE/plugins/phonon_backend QT += phonon TARGET = phonon_mmf PHONON_MMF_DIR = $$QT_SOURCE_TREE/src/3rdparty/phonon/mmf -LIBS += -lDrmAudioPlayUtility.lib +LIBS += -lDrmAudioPlayUtility.lib HEADERS += \ $$PHONON_MMF_DIR/audiooutput.h \ @@ -22,3 +22,11 @@ include(../../qpluginbase.pri) # In the internal 5th SDK, DrmAudioSamplePlayer.h is placed in this folder, as # opposed to the public, where it is placed in epoc32/include. INCLUDEPATH *= /epoc32/include/osextensions + +# We need this to be able to resolve ambiguity for VideoPlayer.h. Phonon has +# it, and the SDK has it. +INCLUDEPATH *= /epoc32/include/osextensions /epoc32 + +# Temporary steal one of the reserved, until we know that this MMF plugin is +# turning into something at all. +symbian:TARGET.UID3=0x2001E627 -- cgit v0.12 From 3b08ceebd0c944f6d60bfced9b263371eb6379bc Mon Sep 17 00:00:00 2001 From: Frans Englich Date: Tue, 21 Jul 2009 02:16:05 +0200 Subject: Include Phonon plugins for Symbian. --- src/plugins/plugins.pro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/plugins.pro b/src/plugins/plugins.pro index c08056e..7fb1886 100644 --- a/src/plugins/plugins.pro +++ b/src/plugins/plugins.pro @@ -9,5 +9,5 @@ unix { !embedded:SUBDIRS *= graphicssystems embedded:SUBDIRS *= gfxdrivers decorations mousedrivers kbddrivers !win32:!embedded:!mac:SUBDIRS *= inputmethods -contains(QT_CONFIG, phonon): SUBDIRS *= phonon symbian:SUBDIRS = imageformats codecs iconengines s60 sqldrivers +contains(QT_CONFIG, phonon): SUBDIRS *= phonon -- cgit v0.12 From 127c93b8ab606740fa9c59de9ce6d10de91af412 Mon Sep 17 00:00:00 2001 From: Frans Englich Date: Tue, 21 Jul 2009 05:35:01 +0200 Subject: Add the Phonon MMF backend. --- src/s60installs/qt.iby | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/s60installs/qt.iby b/src/s60installs/qt.iby index 79edc56..edd0ab2 100644 --- a/src/s60installs/qt.iby +++ b/src/s60installs/qt.iby @@ -70,6 +70,9 @@ file=ABI_DIR\BUILD_DIR\qtwcodecs.dll SHARED_LIB_DIR\qtwcodecs.dll PAG // iconengines file=ABI_DIR\BUILD_DIR\qsvgicon.dll SHARED_LIB_DIR\qsvgicon.dll PAGED +// Phonon MMF backend +file=ABI_DIR\BUILD_DIR\phonon_mmf.dll SHARED_LIB_DIR\phonon_mmf.dll PAGED + S60_APP_RESOURCE(s60main) // imageformats stubs @@ -89,6 +92,9 @@ data=\epoc32\winscw\c\resource\qt\plugins\codecs\qtwcodecs.qtplugin res // iconengines stubs data=\epoc32\winscw\c\resource\qt\plugins\iconengines\qsvgicon.qtplugin resource\qt\plugins\iconengines\qsvgicon.qtplugin +// Phonon MMF backend +data=\epoc32\winscw\c\resource\qt\plugins\phonon_backend\phonon_mmf.qtplugin resource\qt\plugins\phonon_backend\phonon_mmf.qtplugin + // Stub sis file data=ZSYSTEM\install\qt.sis System\Install\qt.sis -- cgit v0.12 From 287b6fbddde1e61776676996471256a3b487e4fd Mon Sep 17 00:00:00 2001 From: Frans Englich Date: Tue, 21 Jul 2009 11:58:13 +0200 Subject: Deploy the Phonon MMF Plugin. --- src/s60installs/qt_libs.pro | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/s60installs/qt_libs.pro b/src/s60installs/qt_libs.pro index bd5c67f..376007e 100644 --- a/src/s60installs/qt_libs.pro +++ b/src/s60installs/qt_libs.pro @@ -54,7 +54,13 @@ symbian: { codecs_plugins.sources = qcncodecs.dll qjpcodecs.dll qtwcodecs.dll qkrcodecs.dll codecs_plugins.path = $$QT_PLUGINS_BASE_DIR/codecs - + + contains(QT_CONFIG, phonon_backend) { + phonon_backend_plugins.sources += phonon_mmf.dll + phonon_backend_plugins.path = $$QT_PLUGINS_BASE_DIR/phonon_backend + DEPLOYMENT += phonon_backend_plugins + } + DEPLOYMENT += qtresources qtlibraries imageformats_plugins codecs_plugins graphicssystems_plugins contains(QT_CONFIG, svg): { -- cgit v0.12 From 7bd7c88d4e555131af035cb7262a5b0b663f63f0 Mon Sep 17 00:00:00 2001 From: Frans Englich Date: Tue, 21 Jul 2009 13:29:39 +0200 Subject: Work. --- src/3rdparty/phonon/mmf/mediaobject.cpp | 30 ++++++++++++++++++++---------- src/3rdparty/phonon/mmf/mediaobject.h | 12 ++++++++---- src/plugins/phonon/mmf/mmf.pro | 10 ++++++---- 3 files changed, 34 insertions(+), 18 deletions(-) diff --git a/src/3rdparty/phonon/mmf/mediaobject.cpp b/src/3rdparty/phonon/mmf/mediaobject.cpp index 605fe24..0763c42 100644 --- a/src/3rdparty/phonon/mmf/mediaobject.cpp +++ b/src/3rdparty/phonon/mmf/mediaobject.cpp @@ -185,16 +185,6 @@ void MMF::MediaObject::setTransitionTime(qint32) { } -void MMF::MediaObject::MaloLoadingComplete() -{ - transitTo(StoppedState); -} - -void MMF::MediaObject::MaloLoadingStarted() -{ - transitTo(LoadingState); -} - void MMF::MediaObject::MdapcInitComplete(TInt aError, const TTimeIntervalMicroSeconds &) { @@ -236,3 +226,23 @@ Phonon::State MMF::MediaObject::state() const return m_state; } +void MMF::MediaObject::MaloLoadingComplete() +{ + transitTo(StoppedState); +} + +void MMF::MediaObject::MaloLoadingStarted() +{ + transitTo(LoadingState); +} + +void MMF::MediaObject::MvloLoadingComplete() +{ + transitTo(StoppedState); +} + +void MMF::MediaObject::MvloLoadingStarted() +{ + transitTo(LoadingState); +} + diff --git a/src/3rdparty/phonon/mmf/mediaobject.h b/src/3rdparty/phonon/mmf/mediaobject.h index 207cb91..ae3cbeb 100644 --- a/src/3rdparty/phonon/mmf/mediaobject.h +++ b/src/3rdparty/phonon/mmf/mediaobject.h @@ -78,15 +78,19 @@ namespace Phonon virtual qint32 transitionTime() const; virtual void setTransitionTime(qint32); - // MAudioLoadingObserver - virtual void MaloLoadingComplete(); - virtual void MaloLoadingStarted(); - // MDrmAudioPlayerCallback virtual void MdapcInitComplete(TInt aError, const TTimeIntervalMicroSeconds &aDuration); virtual void MdapcPlayComplete(TInt aError); + // MAudioLoadingObserver + virtual void MaloLoadingComplete(); + virtual void MaloLoadingStarted(); + + // MVideoLoadingObserver + virtual void MvloLoadingComplete(); + virtual void MvloLoadingStarted(); + Q_SIGNALS: void totalTimeChanged(); void stateChanged(Phonon::State oldState, diff --git a/src/plugins/phonon/mmf/mmf.pro b/src/plugins/phonon/mmf/mmf.pro index 1a1d435..6d404f2 100644 --- a/src/plugins/phonon/mmf/mmf.pro +++ b/src/plugins/phonon/mmf/mmf.pro @@ -1,4 +1,3 @@ -DESTDIR = $$QT_BUILD_TREE/plugins/phonon_backend QT += phonon TARGET = phonon_mmf PHONON_MMF_DIR = $$QT_SOURCE_TREE/src/3rdparty/phonon/mmf @@ -14,6 +13,9 @@ SOURCES += \ $$PHONON_MMF_DIR/backend.cpp \ $$PHONON_MMF_DIR/mediaobject.cpp +# This is needed for having the .qtplugin file properly created on Symbian. +QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/phonon_backend + target.path = $$[QT_INSTALL_PLUGINS]/phonon_backend INSTALLS += target @@ -23,9 +25,9 @@ include(../../qpluginbase.pri) # opposed to the public, where it is placed in epoc32/include. INCLUDEPATH *= /epoc32/include/osextensions -# We need this to be able to resolve ambiguity for VideoPlayer.h. Phonon has -# it, and the SDK has it. -INCLUDEPATH *= /epoc32/include/osextensions /epoc32 +# We need this to be able to resolve ambiguity for VideoPlayer.h. Phonon and +# the SDK has the header. +INCLUDEPATH *= /epoc32 # Temporary steal one of the reserved, until we know that this MMF plugin is # turning into something at all. -- cgit v0.12 From 1e08ccc646e4f07fd560c901ff7b56626ed98d1e Mon Sep 17 00:00:00 2001 From: Frans Englich Date: Tue, 21 Jul 2009 16:09:27 +0200 Subject: Crash fixes. --- src/3rdparty/phonon/mmf/audiooutput.h | 8 +++++--- src/3rdparty/phonon/mmf/mediaobject.h | 1 + 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/3rdparty/phonon/mmf/audiooutput.h b/src/3rdparty/phonon/mmf/audiooutput.h index 02dd046..8c0de1f 100644 --- a/src/3rdparty/phonon/mmf/audiooutput.h +++ b/src/3rdparty/phonon/mmf/audiooutput.h @@ -29,9 +29,9 @@ namespace Phonon class MediaObject; /** - * @short AudioOutputInterface42 implementation for MMF. + * @short AudioOutputInterface implementation for MMF. * - * Implements the AudioOutputInterface42 for Symbian/S60's MMF + * Implements the AudioOutputInterface for Symbian/S60's MMF * framework. * * This class has a very small role, we simply access CDrmPlayerUtility @@ -47,9 +47,11 @@ namespace Phonon * @author Frans Englich */ class AudioOutput : public QObject - , public AudioOutputInterface42 + , public AudioOutputInterface { Q_OBJECT + Q_INTERFACES(Phonon::AudioOutputInterface) + public: AudioOutput(Backend *backend, QObject *parent); virtual qreal volume() const; diff --git a/src/3rdparty/phonon/mmf/mediaobject.h b/src/3rdparty/phonon/mmf/mediaobject.h index ae3cbeb..0631e4a 100644 --- a/src/3rdparty/phonon/mmf/mediaobject.h +++ b/src/3rdparty/phonon/mmf/mediaobject.h @@ -52,6 +52,7 @@ namespace Phonon { Q_OBJECT Q_INTERFACES(Phonon::MediaObjectInterface) + public: MediaObject(QObject *parent); virtual ~MediaObject(); -- cgit v0.12 From 598ee0994a7ca14ef0bc4265dab99d716ba6f189 Mon Sep 17 00:00:00 2001 From: Frans Englich Date: Tue, 11 Aug 2009 17:19:51 +0200 Subject: Revert "QItemSelectionModel did not send selectionChanged signal when deleting an item" This reverts commit d13418effc5f00474541ae513a30c9a42c2a1cb3. --- src/gui/itemviews/qitemselectionmodel.cpp | 22 +------------------- src/gui/itemviews/qitemselectionmodel_p.h | 2 -- .../tst_qitemselectionmodel.cpp | 24 ---------------------- 3 files changed, 1 insertion(+), 47 deletions(-) diff --git a/src/gui/itemviews/qitemselectionmodel.cpp b/src/gui/itemviews/qitemselectionmodel.cpp index 0f35ac1..9dad95f 100644 --- a/src/gui/itemviews/qitemselectionmodel.cpp +++ b/src/gui/itemviews/qitemselectionmodel.cpp @@ -593,30 +593,10 @@ void QItemSelectionModelPrivate::_q_rowsAboutToBeRemoved(const QModelIndex &pare // update selectionsx QModelIndex tl = model->index(start, 0, parent); QModelIndex br = model->index(end, model->columnCount(parent) - 1, parent); - recursiveDeselect(QItemSelectionRange(tl, br)); + q->select(QItemSelection(tl, br), QItemSelectionModel::Deselect); finalize(); } -void QItemSelectionModelPrivate::recursiveDeselect(const QItemSelectionRange &range) -{ - Q_Q(QItemSelectionModel); - - QItemSelection sel(range.topLeft(), range.bottomRight()); - q->select(sel, QItemSelectionModel::Deselect); - - QModelIndexList idxList = range.indexes(); - QModelIndexList::const_iterator it = idxList.begin(); - for (; it != idxList.end(); ++it) - { - if (!model->hasChildren(*it)) - continue; - - const QModelIndex &firstChild = it->child(0,0); - const QModelIndex &lastChild = it->child(model->rowCount(*it) - 1, model->columnCount(*it) - 1); - recursiveDeselect(QItemSelectionRange(firstChild, lastChild)); - } -} - /*! \internal */ diff --git a/src/gui/itemviews/qitemselectionmodel_p.h b/src/gui/itemviews/qitemselectionmodel_p.h index 8176d4c..18ad506 100644 --- a/src/gui/itemviews/qitemselectionmodel_p.h +++ b/src/gui/itemviews/qitemselectionmodel_p.h @@ -77,8 +77,6 @@ public: void _q_layoutAboutToBeChanged(); void _q_layoutChanged(); - void recursiveDeselect(const QItemSelectionRange &range); - inline void remove(QList &r) { QList::const_iterator it = r.constBegin(); diff --git a/tests/auto/qitemselectionmodel/tst_qitemselectionmodel.cpp b/tests/auto/qitemselectionmodel/tst_qitemselectionmodel.cpp index 05e23f1..0541b46 100644 --- a/tests/auto/qitemselectionmodel/tst_qitemselectionmodel.cpp +++ b/tests/auto/qitemselectionmodel/tst_qitemselectionmodel.cpp @@ -90,7 +90,6 @@ private slots: void merge(); void task119433_isRowSelected(); void task252069_rowIntersectsSelection(); - void task232634_childrenDeselectionSignal(); private: QAbstractItemModel *model; @@ -2188,28 +2187,5 @@ void tst_QItemSelectionModel::task252069_rowIntersectsSelection() QVERIFY(!selected.columnIntersectsSelection(5, QModelIndex())); } -void tst_QItemSelectionModel::task232634_childrenDeselectionSignal() -{ - QStandardItemModel model; - - QStandardItem *parentItem = model.invisibleRootItem(); - for (int i = 0; i < 4; ++i) { - QStandardItem *item = new QStandardItem(QString("item %0").arg(i)); - parentItem->appendRow(item); - parentItem = item; - } - - QModelIndex root = model.index(0,0); - QModelIndex par = root.child(0,0); - QModelIndex sel = par.child(0,0); - - QItemSelectionModel selectionModel(&model); - selectionModel.select(sel, QItemSelectionModel::SelectCurrent); - - QSignalSpy deselectSpy(&selectionModel, SIGNAL(selectionChanged(const QItemSelection& , const QItemSelection&))); - model.removeRows(0, 1, root); - QVERIFY(deselectSpy.count() == 1); -} - QTEST_MAIN(tst_QItemSelectionModel) #include "tst_qitemselectionmodel.moc" -- cgit v0.12 From 44265f30fb40baaecd4cda1b5aca0efeed6abc20 Mon Sep 17 00:00:00 2001 From: Frans Englich Date: Wed, 12 Aug 2009 16:11:00 +0200 Subject: Commit patch by Gareth. The patch originally contained all changed done to MMF Phonon, but this commit contains the changes only Gareth did. --- src/3rdparty/phonon/mmf/audiooutput.cpp | 50 ++- src/3rdparty/phonon/mmf/audiooutput.h | 13 +- src/3rdparty/phonon/mmf/backend.cpp | 3 +- src/3rdparty/phonon/mmf/mediaobject.cpp | 523 +++++++++++++++++++++++++++----- src/3rdparty/phonon/mmf/mediaobject.h | 95 ++++-- src/3rdparty/phonon/mmf/utils.cpp | 46 +++ src/3rdparty/phonon/mmf/utils.h | 134 ++++++++ src/plugins/phonon/mmf/mmf.pro | 30 +- src/plugins/plugins.pro | 1 + 9 files changed, 765 insertions(+), 130 deletions(-) create mode 100644 src/3rdparty/phonon/mmf/utils.cpp create mode 100644 src/3rdparty/phonon/mmf/utils.h diff --git a/src/3rdparty/phonon/mmf/audiooutput.cpp b/src/3rdparty/phonon/mmf/audiooutput.cpp index 9d1ff02..9c8cb6b 100644 --- a/src/3rdparty/phonon/mmf/audiooutput.cpp +++ b/src/3rdparty/phonon/mmf/audiooutput.cpp @@ -16,39 +16,45 @@ along with this library. If not, see . */ -#include - #include "mediaobject.h" #include "audiooutput.h" +#include "utils.h" using namespace Phonon; using namespace Phonon::MMF; -MMF::AudioOutput::AudioOutput(Backend *, QObject *parent) : m_mediaObject(0) - , m_volume(0) - , m_maxVolume(-1) +MMF::AudioOutput::AudioOutput(Backend *, QObject *parent) : m_mediaObject(NULL) { setParent(parent); } qreal MMF::AudioOutput::volume() const { - return 0; + TRACE_CONTEXT(AudioOutput::volume, EAudioApi); + TRACE_ENTRY("m_mediaObject 0x%08x", m_mediaObject); + + const qreal result = m_mediaObject ? m_mediaObject->volume() : 0.0; + + TRACE_RETURN("%f", result); } -void MMF::AudioOutput::setVolume(qreal newVolume) +void MMF::AudioOutput::setVolume(qreal volume) { - if(!m_mediaObject) - return; + TRACE_CONTEXT(AudioOutput::setVolume, EAudioApi); + TRACE_ENTRY("volume %f", volume); - Q_ASSERT(m_mediaObject->m_player); + if(m_mediaObject and m_mediaObject->setVolume(volume)) + { + TRACE("emit volumeChanged(%f)", volume) + emit volumeChanged(volume); + } - if (newVolume == m_volume) - return; + TRACE_EXIT_0(); +} - m_volume = newVolume; - m_mediaObject->m_player->SetVolume(newVolume * m_maxVolume); - emit volumeChanged(m_volume); +void MMF::AudioOutput::triggerVolumeChanged(qreal volume) +{ + emit volumeChanged(volume); } int MMF::AudioOutput::outputDevice() const @@ -68,19 +74,7 @@ bool MMF::AudioOutput::setOutputDevice(const Phonon::AudioOutputDevice &) void MMF::AudioOutput::setMediaObject(MediaObject *mo) { - Q_ASSERT(m_mediaObject); + 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 8c0de1f..5e4fef2 100644 --- a/src/3rdparty/phonon/mmf/audiooutput.h +++ b/src/3rdparty/phonon/mmf/audiooutput.h @@ -55,7 +55,7 @@ namespace Phonon public: AudioOutput(Backend *backend, QObject *parent); virtual qreal volume() const; - virtual void setVolume(qreal); + virtual void setVolume(qreal volume); virtual int outputDevice() const; @@ -71,13 +71,18 @@ namespace Phonon void setMediaObject(MediaObject *mo); + /** + * Called by MediaObject to pass initial volume when clip has been + * successfully opened + */ + void triggerVolumeChanged(qreal volume); + Q_SIGNALS: - void volumeChanged(qreal newVolume); + void volumeChanged(qreal volume); + void audioDeviceFailed(); 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 4324409..3152603 100644 --- a/src/3rdparty/phonon/mmf/backend.cpp +++ b/src/3rdparty/phonon/mmf/backend.cpp @@ -75,7 +75,7 @@ QHash Backend::objectDescriptionProperties(ObjectDescripti bool Backend::startConnectionChange(QSet) { - return false; + return true; } bool Backend::connectNodes(QObject *source, QObject *target) @@ -87,6 +87,7 @@ bool Backend::connectNodes(QObject *source, QObject *target) return false; ao->setMediaObject(mo); + mo->setAudioOutput(ao); return true; } diff --git a/src/3rdparty/phonon/mmf/mediaobject.cpp b/src/3rdparty/phonon/mmf/mediaobject.cpp index 0763c42..8a4b76e 100644 --- a/src/3rdparty/phonon/mmf/mediaobject.cpp +++ b/src/3rdparty/phonon/mmf/mediaobject.cpp @@ -17,188 +17,473 @@ along with this library. If not, see . */ #include +#include #include #include "mediaobject.h" +#include "audiooutput.h" +#include "utils.h" using namespace Phonon; using namespace Phonon::MMF; -MMF::MediaObject::MediaObject(QObject *parent) : m_player(0) +//----------------------------------------------------------------------------- +// Constants +//----------------------------------------------------------------------------- + +const qint32 DefaultTickInterval = 20; +const int NullMaxVolume = -1; + + +//----------------------------------------------------------------------------- +// Constructor / destructor +//----------------------------------------------------------------------------- + +MMF::MediaObject::MediaObject(QObject *parent) : m_player(NULL) + , m_audioOutput(NULL) , m_error(NoError) - , m_state(StoppedState) + , m_state(GroundState) + , m_tickInterval(DefaultTickInterval) + , m_tickTimer(NULL) + , m_volume(0.0) + , m_maxVolume(NullMaxVolume) { + TRACE_CONTEXT(MediaObject::MediaObject, EAudioApi); + TRACE_ENTRY_0(); + Q_UNUSED(parent); - m_player = CDrmPlayerUtility::NewL(*this, 0, EMdaPriorityPreferenceNone); - m_player->RegisterForAudioLoadingNotification(*this); + // TODO: should leaves be trapped in the constructor? + m_player = CPlayerType::NewL(*this, 0, EMdaPriorityPreferenceNone); + + m_tickTimer = new QTimer(this); + connect(m_tickTimer, SIGNAL(timeout()), this, SLOT(tick())); + + TRACE_EXIT_0(); } MMF::MediaObject::~MediaObject() { + TRACE_CONTEXT(MediaObject::~MediaObject, EAudioApi); + TRACE_ENTRY_0(); + + delete m_tickTimer; delete m_player; + + TRACE_EXIT_0(); } +//----------------------------------------------------------------------------- +// MediaObjectInterface +//----------------------------------------------------------------------------- + void MMF::MediaObject::play() { - transitTo(PlayingState); - m_player->Play(); + TRACE_CONTEXT(MediaObject::play, EAudioApi); + TRACE_ENTRY("state %d", m_state); + + switch(m_state) + { + case GroundState: + case LoadingState: + // Is this the correct error? Really we want 'NotReadyError' + m_error = NormalError; + changeState(ErrorState); + break; + + case StoppedState: + case PausedState: + m_player->Play(); + m_tickTimer->start(m_tickInterval); + changeState(PlayingState); + break; + + case PlayingState: + case BufferingState: + case ErrorState: + // Do nothing + break; + + // Protection against adding new states and forgetting to update this switch + default: + TRACE_PANIC(InvalidStatePanic); + } + + TRACE_EXIT("state %d", m_state); } void MMF::MediaObject::pause() { - transitTo(PausedState); - m_player->Pause(); + TRACE_CONTEXT(MediaObject::pause, EAudioApi); + TRACE_ENTRY("state %d", m_state); + + switch(m_state) + { + case GroundState: + case LoadingState: + case StoppedState: + case PausedState: + case ErrorState: + // Do nothing + break; + + case PlayingState: + case BufferingState: + m_player->Pause(); + m_tickTimer->stop(); + changeState(PausedState); + break; + + // Protection against adding new states and forgetting to update this switch + default: + TRACE_PANIC(InvalidStatePanic); + } + + TRACE_EXIT("state %d", m_state); } void MMF::MediaObject::stop() { - transitTo(StoppedState); - m_player->Stop(); + TRACE_CONTEXT(MediaObject::stop, EAudioApi); + TRACE_ENTRY("state %d", m_state); + + switch(m_state) + { + case GroundState: + case LoadingState: + case StoppedState: + case ErrorState: + // Do nothing + break; + + case PlayingState: + case BufferingState: + case PausedState: + m_player->Stop(); + m_tickTimer->stop(); + changeState(StoppedState); + break; + + // Protection against adding new states and forgetting to update this switch + default: + TRACE_PANIC(InvalidStatePanic); + } + + TRACE_EXIT("state %d", m_state); } -void MMF::MediaObject::seek(qint64 milliseconds) +void MMF::MediaObject::seek(qint64 ms) { - m_player->SetPosition(toMicroSeconds(milliseconds)); + TRACE_CONTEXT(MediaObject::seek, EAudioApi); + TRACE_ENTRY("state %d pos %Ld", m_state, ms); + + m_player->SetPosition(TTimeIntervalMicroSeconds(ms)); + + TRACE_EXIT_0(); } qint32 MMF::MediaObject::tickInterval() const { - return 0; + TRACE_CONTEXT(MediaObject::tickInterval, EAudioApi); + TRACE_ENTRY("state %d", m_state); + + TRACE_RETURN("%d", m_tickInterval); } void MMF::MediaObject::setTickInterval(qint32 interval) { - Q_UNUSED(interval); + TRACE_CONTEXT(MediaObject::setTickInterval, EAudioApi); + TRACE_ENTRY("state %d m_interval %d interval %d", m_state, m_tickInterval, interval); + + m_tickInterval = interval; + m_tickTimer->setInterval(interval); + + TRACE_EXIT_0(); } bool MMF::MediaObject::hasVideo() const { - return false; + TRACE_CONTEXT(MediaObject::hasVideo, EAudioApi); + TRACE_ENTRY("state %d", m_state); + + // TODO: re-factor this class so that audio playback and video playback are + // delegated to separate classes, which internally hoat a + // CMdaAudioPlayerUtility / CVideoPlayerUtility instance as appropriate. + + TRACE_RETURN("%d", false); } bool MMF::MediaObject::isSeekable() const { - return false; + TRACE_CONTEXT(MediaObject::isSeekable, EAudioApi); + TRACE_ENTRY("state %d", m_state); + + TRACE_RETURN("%d", true); +} + +Phonon::State MMF::MediaObject::state() const +{ + TRACE_CONTEXT(MediaObject::state, EAudioApi); + TRACE_ENTRY("state %d", m_state); + + const Phonon::State result = phononState(m_state); + + TRACE_RETURN("%d", result); } qint64 MMF::MediaObject::currentTime() const { - TTimeIntervalMicroSeconds mss; - const TInt retcode = m_player->GetPosition(mss); + TRACE_CONTEXT(MediaObject::currentTime, EAudioApi); + TRACE_ENTRY("state %d", m_state); - if(retcode == KErrNone) - return toMilliSeconds(m_player->Duration()); - else { - // TODO Should we enter/emit error state? Tricky - // since we're in a const function. - return -1; + TTimeIntervalMicroSeconds us; + const TInt err = m_player->GetPosition(us); + + qint64 result = -1; + + if(KErrNone == err) { + result = toMilliSeconds(us); } + + TRACE_RETURN("%Ld", result); } QString MMF::MediaObject::errorString() const { - return QString(); + TRACE_CONTEXT(MediaObject::errorString, EAudioApi); + TRACE_ENTRY("state %d", m_state); + + TRACE_EXIT_0(); + // TODO: put in proper error strings + QString result; + return result; } Phonon::ErrorType MMF::MediaObject::errorType() const { - return m_error; -} + TRACE_CONTEXT(MediaObject::errorType, EAudioApi); + TRACE_ENTRY("state %d", m_state); -qint64 MMF::MediaObject::toMilliSeconds(const TTimeIntervalMicroSeconds &in) -{ - return in.Int64() / 1000; -} + const Phonon::ErrorType result = (ErrorState == m_state) + ? m_error : NoError; -TTimeIntervalMicroSeconds MMF::MediaObject::toMicroSeconds(qint64 ms) -{ - return TTimeIntervalMicroSeconds(TInt64(ms)); + TRACE_RETURN("%d", result); } qint64 MMF::MediaObject::totalTime() const { - return toMilliSeconds(m_player->Duration()); + TRACE_CONTEXT(MediaObject::totalTime, EAudioApi); + TRACE_ENTRY("state %d", m_state); + + const qint64 result = toMilliSeconds(m_player->Duration()); + + TRACE_RETURN("%Ld", result); } MediaSource MMF::MediaObject::source() const { + TRACE_CONTEXT(MediaObject::source, EAudioApi); + TRACE_ENTRY("state %d", m_state); + + TRACE_EXIT_0(); return m_mediaSource; } void MMF::MediaObject::setSource(const MediaSource &source) { - stop(); + TRACE_CONTEXT(MediaObject::setSource, EAudioApi); + TRACE_ENTRY("state %d source.type %d", m_state, source.type()); + + m_player->Close(); + changeState(GroundState); + + // TODO: is it correct to assign even if the media type is not supported in + // the switch statement below? m_mediaSource = source; + TInt symbianErr = KErrNone; + switch(m_mediaSource.type()) { case MediaSource::LocalFile: { - const QHBufC filename(source.fileName()); - m_player->OpenFileL(*filename); + // TODO: work out whose responsibility it is to ensure that paths + // are Symbian-style, i.e. have backslashes for path delimiters. + // Until then, use this utility function... + const QHBufC filename = Utils::symbianFilename(m_mediaSource.fileName()); + TRAP(symbianErr, m_player->OpenFileL(*filename)); break; } + case MediaSource::Url: { - const QHBufC filename(source.url().toString()); - m_player->OpenUrlL(*filename); + const QHBufC filename(m_mediaSource.url().toString()); + TRAP(symbianErr, m_player->OpenUrlL(*filename)); break; } + case MediaSource::Invalid: - /* Fallthrough. */ case MediaSource::Disc: - /* Fallthrough. */ case MediaSource::Stream: - /* Fallthrough. */ + symbianErr = KErrNotSupported; + break; + case MediaSource::Empty: - { - transitTo(ErrorState); + TRACE_EXIT_0(); return; - } + + // Protection against adding new media types and forgetting to update this switch + default: + TRACE_PANIC(InvalidMediaTypePanic); + } + + if(KErrNone == symbianErr) + { +#ifdef QT_PHONON_MMF_AUDIO_DRM + // There appears to be a bug in the CDrmPlayerUtility implementation (at least + // in S60 5.x) whereby the player does not check whether the loading observer + // pointer is null before dereferencing it. Therefore we must register for + // loading notification, even though we do nothing in the callback functions. + m_player->RegisterForAudioLoadingNotification(*this); +#endif + changeState(LoadingState); + } + else + { + // TODO: do something with the value of symbianErr? + m_error = NormalError; + changeState(ErrorState); } - transitTo(LoadingState); + TRACE_EXIT_0(); } void MMF::MediaObject::setNextSource(const MediaSource &source) { + TRACE_CONTEXT(MediaObject::setNextSource, EAudioApi); + TRACE_ENTRY("state %d", m_state); + + // TODO: handle 'next source' + m_nextSource = source; Q_UNUSED(source); + + TRACE_EXIT_0(); } qint32 MMF::MediaObject::prefinishMark() const { - return 0; + TRACE_CONTEXT(MediaObject::prefinishMark, EAudioApi); + TRACE_ENTRY("state %d", m_state); + + // TODO: implement prefinish mark + const qint32 result = 0; + TRACE_RETURN("%d", result); } -void MMF::MediaObject::setPrefinishMark(qint32) +void MMF::MediaObject::setPrefinishMark(qint32 mark) { + TRACE_CONTEXT(MediaObject::setPrefinishMark, EAudioApi); + TRACE_ENTRY("state %d mark %d", m_state, mark); + Q_UNUSED(mark); // to silence warnings in release builds + + // TODO: implement prefinish mark + + TRACE_EXIT_0(); } qint32 MMF::MediaObject::transitionTime() const { - return 0; + TRACE_CONTEXT(MediaObject::transitionTime, EAudioApi); + TRACE_ENTRY("state %d", m_state); + + // TODO: implement transition time + const qint32 result = 0; + TRACE_RETURN("%d", result); } -void MMF::MediaObject::setTransitionTime(qint32) +void MMF::MediaObject::setTransitionTime(qint32 time) { + TRACE_CONTEXT(MediaObject::setTransitionTime, EAudioApi); + TRACE_ENTRY("state %d time %d", m_state, time); + Q_UNUSED(time); // to silence warnings in release builds + + // TODO: implement transition time + + TRACE_EXIT_0(); } + +//----------------------------------------------------------------------------- +// Symbian multimedia client observer callbacks +//----------------------------------------------------------------------------- + +#ifdef QT_PHONON_MMF_AUDIO_DRM void MMF::MediaObject::MdapcInitComplete(TInt aError, const TTimeIntervalMicroSeconds &) +#else +void MMF::MediaObject::MapcInitComplete(TInt aError, + const TTimeIntervalMicroSeconds &) +#endif { - if(aError == KErrNone) { + TRACE_CONTEXT(MediaObject::MapcInitComplete, EAudioInternal); + TRACE_ENTRY("state %d error %d", m_state, aError); + + __ASSERT_ALWAYS(LoadingState == m_state, Utils::panic(InvalidStatePanic)); + + if(KErrNone == aError) + { + TInt volume = 0; + aError = m_player->GetVolume(volume); + if(KErrNone == aError) + { + m_maxVolume = m_player->MaxVolume(); + m_volume = static_cast(volume) / m_maxVolume; + + if(m_audioOutput) + { + // Trigger AudioOutput signal + m_audioOutput->triggerVolumeChanged(m_volume); + } + + emit totalTimeChanged(); + changeState(StoppedState); + } + } + else + { + // TODO: set different error states according to value of aError? m_error = NormalError; - m_state = ErrorState; + changeState(ErrorState); } - emit totalTimeChanged(); - transitTo(StoppedState); + TRACE_EXIT_0(); } +#ifdef QT_PHONON_MMF_AUDIO_DRM void MMF::MediaObject::MdapcPlayComplete(TInt aError) +#else +void MMF::MediaObject::MapcPlayComplete(TInt aError) +#endif { + TRACE_CONTEXT(MediaObject::MapcPlayComplete, EAudioInternal); + TRACE_ENTRY("state %d error %d", m_state, aError); + + m_tickTimer->stop(); + + if(KErrNone == aError) + { + changeState(StoppedState); + // TODO: move on to m_nextSource + } + else + { + // TODO: do something with aError? + m_error = NormalError; + changeState(ErrorState); + } + +/* if(aError == KErrNone) { if(m_nextSource.type() == MediaSource::Empty) { emit finished(); @@ -207,42 +492,140 @@ void MMF::MediaObject::MdapcPlayComplete(TInt aError) m_nextSource = MediaSource(); } - transitTo(StoppedState); + changeState(StoppedState); } else { m_error = NormalError; - transitTo(ErrorState); + changeState(ErrorState); } +*/ + + TRACE_EXIT_0(); } -void MMF::MediaObject::transitTo(Phonon::State newState) +#ifdef QT_PHONON_MMF_AUDIO_DRM +void MMF::MediaObject::MaloLoadingStarted() { - emit stateChanged(m_state, newState); - m_state = newState; + } -Phonon::State MMF::MediaObject::state() const +void MMF::MediaObject::MaloLoadingComplete() { - return m_state; + } +#endif // QT_PHONON_MMF_AUDIO_DRM -void MMF::MediaObject::MaloLoadingComplete() + +//----------------------------------------------------------------------------- +// Volume +//----------------------------------------------------------------------------- + +qreal MMF::MediaObject::volume() const { - transitTo(StoppedState); + return m_volume; } -void MMF::MediaObject::MaloLoadingStarted() +bool MMF::MediaObject::setVolume(qreal volume) { - transitTo(LoadingState); + TRACE_CONTEXT(MediaObject::setVolume, EAudioInternal); + TRACE_ENTRY("state %d", m_state); + + bool volumeChanged = false; + + switch(m_state) + { + case GroundState: + case LoadingState: + case ErrorState: + // Do nothing + break; + + case StoppedState: + case PausedState: + case PlayingState: + case BufferingState: + { + if(volume != m_volume) + { + const int err = m_player->SetVolume(volume * m_maxVolume); + if(KErrNone == err) + { + m_volume = volume; + volumeChanged = true; + } + else + { + m_error = NormalError; + changeState(ErrorState); + } + } + break; + } + + // Protection against adding new states and forgetting to update this + // switch + default: + TRACE_PANIC(InvalidStatePanic); + } + + TRACE_RETURN("%d", volumeChanged); } -void MMF::MediaObject::MvloLoadingComplete() +void MMF::MediaObject::setAudioOutput(AudioOutput* audioOutput) { - transitTo(StoppedState); + m_audioOutput = audioOutput; } -void MMF::MediaObject::MvloLoadingStarted() + +//----------------------------------------------------------------------------- +// Private functions +//----------------------------------------------------------------------------- + +qint64 MMF::MediaObject::toMilliSeconds(const TTimeIntervalMicroSeconds &in) { - transitTo(LoadingState); + return in.Int64() / 1000; } +Phonon::State MMF::MediaObject::phononState(PrivateState state) +{ + const Phonon::State phononState = + GroundState == state + ? Phonon::StoppedState + : static_cast(state); + + return phononState; +} + +void MMF::MediaObject::changeState(PrivateState newState) +{ + TRACE_CONTEXT(MediaObject::changeState, EAudioInternal); + TRACE_ENTRY("state %d newState %d", m_state, newState); + + // TODO: add some invariants to check that the transition is valid + + const Phonon::State currentPhononState = phononState(m_state); + const Phonon::State newPhononState = phononState(newState); + if(currentPhononState != newPhononState) + { + TRACE("emit stateChanged(%d, %d)", newPhononState, currentPhononState); + emit stateChanged(newPhononState, currentPhononState); + } + + m_state = newState; + + TRACE_EXIT_0(); +} + +void MMF::MediaObject::tick() +{ + TRACE_CONTEXT(MediaObject::tick, EAudioInternal); + TRACE_ENTRY("state %d", m_state); + + emit tick(currentTime()); + + TRACE_EXIT_0(); +} + + + + diff --git a/src/3rdparty/phonon/mmf/mediaobject.h b/src/3rdparty/phonon/mmf/mediaobject.h index 0631e4a..f17580e 100644 --- a/src/3rdparty/phonon/mmf/mediaobject.h +++ b/src/3rdparty/phonon/mmf/mediaobject.h @@ -21,15 +21,24 @@ along with this library. If not, see . /* We use the extra qualification include/ to avoid picking up the include * Phonon has. */ -#include - -#include +#include #include #include class CDrmPlayerUtility; class TTimeIntervalMicroSeconds; +class QTimer; + +#ifdef QT_PHONON_MMF_AUDIO_DRM +#include +typedef CDrmPlayerUtility CPlayerType; +typedef MDrmAudioPlayerCallback MPlayerObserverType; +#else +#include +typedef CMdaAudioPlayerUtility CPlayerType; +typedef MMdaAudioPlayerCallback MPlayerObserverType; +#endif namespace Phonon { @@ -45,10 +54,10 @@ namespace Phonon */ class MediaObject : public QObject , public MediaObjectInterface - , public MDrmAudioPlayerCallback - , public MAudioLoadingObserver - , public MVideoLoadingObserver - //, public MVideoPlayerUtilityObserver + , public MPlayerObserverType // typedef +#ifdef QT_PHONON_MMF_AUDIO_DRM + , public MAudioLoadingObserver +#endif { Q_OBJECT Q_INTERFACES(Phonon::MediaObjectInterface) @@ -79,45 +88,91 @@ namespace Phonon virtual qint32 transitionTime() const; virtual void setTransitionTime(qint32); +#ifdef QT_PHONON_MMF_AUDIO_DRM // MDrmAudioPlayerCallback virtual void MdapcInitComplete(TInt aError, const TTimeIntervalMicroSeconds &aDuration); virtual void MdapcPlayComplete(TInt aError); // MAudioLoadingObserver - virtual void MaloLoadingComplete(); virtual void MaloLoadingStarted(); + virtual void MaloLoadingComplete(); +#else + // MMdaAudioPlayerCallback + virtual void MapcInitComplete(TInt aError, + const TTimeIntervalMicroSeconds &aDuration); + virtual void MapcPlayComplete(TInt aError); +#endif + + qreal volume() const; + bool setVolume(qreal volume); - // MVideoLoadingObserver - virtual void MvloLoadingComplete(); - virtual void MvloLoadingStarted(); + void setAudioOutput(AudioOutput* audioOutput); Q_SIGNALS: void totalTimeChanged(); void stateChanged(Phonon::State oldState, Phonon::State newState); - void finished(); + void tick(qint64 time); + + private Q_SLOTS: + /** + * Receives signal from m_tickTimer + */ + void tick(); private: - friend class AudioOutput; - static inline qint64 toMilliSeconds(const TTimeIntervalMicroSeconds &); - static inline TTimeIntervalMicroSeconds toMicroSeconds(qint64 ms); + static qint64 toMilliSeconds(const TTimeIntervalMicroSeconds &); /** - * Changes state() to \a newState, and emits stateChanged(). + * Defined private state enumeration in order to add GroundState */ - inline void transitTo(Phonon::State newState); + enum PrivateState + { + LoadingState = Phonon::LoadingState, + StoppedState = Phonon::StoppedState, + PlayingState = Phonon::PlayingState, + BufferingState = Phonon::BufferingState, + PausedState = Phonon::PausedState, + ErrorState = Phonon::ErrorState, + GroundState + }; + + /** + * Converts PrivateState into the corresponding Phonon::State + */ + static Phonon::State phononState(PrivateState state); + + /** + * Changes state and emits stateChanged() + */ + void changeState(PrivateState newState); + + /** + * Using CPlayerType typedef in order to be able to easily switch between + * CMdaAudioPlayerUtility and CDrmPlayerUtility + */ + CPlayerType* m_player; + + AudioOutput* m_audioOutput; - CDrmPlayerUtility * m_player; ErrorType m_error; /** - * Never update this state by assigning to it. Call transitTo(). + * Do not set this directly - call changeState() instead. */ - State m_state; + PrivateState m_state; + + qint32 m_tickInterval; + + QTimer* m_tickTimer; + MediaSource m_mediaSource; MediaSource m_nextSource; + + qreal m_volume; + int m_maxVolume; }; } } diff --git a/src/3rdparty/phonon/mmf/utils.cpp b/src/3rdparty/phonon/mmf/utils.cpp new file mode 100644 index 0000000..aa87310 --- /dev/null +++ b/src/3rdparty/phonon/mmf/utils.cpp @@ -0,0 +1,46 @@ +/* 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 . + +*/ + +#include "utils.h" +#include + +using namespace Phonon; +using namespace Phonon::MMF; + +_LIT(PanicCategory, "Phonon::MMF"); + +void MMF::Utils::panic(PanicCode code) + { + User::Panic(PanicCategory, code); + } + +QHBufC MMF::Utils::symbianFilename(const QString& qtFilename) +{ + _LIT(ForwardSlash, "/"); + _LIT(BackwardSlash, "\\"); + + QHBufC result(qtFilename); + TInt pos = result->Find(ForwardSlash); + while(pos != KErrNotFound) + { + result->Des().Replace(pos, 1, BackwardSlash); + pos = result->Find(ForwardSlash); + } + + return result; +} diff --git a/src/3rdparty/phonon/mmf/utils.h b/src/3rdparty/phonon/mmf/utils.h new file mode 100644 index 0000000..4b967fc --- /dev/null +++ b/src/3rdparty/phonon/mmf/utils.h @@ -0,0 +1,134 @@ +/* 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 . + +*/ + +#ifndef PHONON_MMF_UTILS_H +#define PHONON_MMF_UTILS_H + +#include + +namespace Phonon +{ + namespace MMF + { + /** + * Panic codes for fatal errors + */ + enum PanicCode + { + InvalidStatePanic, + InvalidMediaTypePanic + }; + + namespace Utils + { + /** + * Raise a fatal exception + */ + void panic(PanicCode code); + + /** + * Translate forward slashes to backslashes + * + * \note This function is a temporary measure, for use until the + * responsibility for constructing valid file paths is + * determined. + */ + QHBufC symbianFilename(const QString& qtFilename); + } + + /** + * Available trace categories; + */ + enum TTraceCategory + { + /** + * Functions which map directly to the public Phonon audio API + */ + EAudioApi = 0x00000001, + + /** + * Internal functions in the audio implementation + */ + EAudioInternal = 0x00000002 + }; + + /** + * Mask indicating which trace categories are enabled + * + * Note that, at the moment, this is a compiled static constant. For + * runtime control over enabled trace categories, this could be replaced + * by a per-thread singleton object which owns the trace mask, and which + * exposes an API allowing it to be modified. + */ + static const TUint KTraceMask = 0xffffffff; + + /** + * Data structure used by tracing macros + */ + class TTraceContext + { + public: + TTraceContext(const TText* aFunction, const TUint aAddr, + const TUint aCategory=0) + : iFunction(aFunction), + iAddr(aAddr), + iCategory(aCategory) + { } + + /** + * Check whether iCategory appears in the trace mask + */ + TBool Enabled() const + { + return (iCategory == 0) or (iCategory & KTraceMask); + } + + const TText* iFunction; // Name of function + const TUint iAddr; // 'this' pointer + const TUint iCategory; + }; + + // Macros used internally by the trace system + #define _TRACE_PRINT RDebug::Print + #define _TRACE_TEXT(x) (TPtrC((const TText *)(x))) + #define _TRACE_MODULE Phonon::MMF + + // Macros available for use by implementation code +#ifdef _DEBUG + #define TRACE_CONTEXT(_fn, _cat) const ::Phonon::MMF::TTraceContext _tc((TText*)L ## #_fn, (TUint)this, _cat); + #define TRACE_ENTRY_0() { if(_tc.Enabled()) _TRACE_PRINT(_TRACE_TEXT(L ## "+ Phonon::MMF::%s [0x%08x]"), _tc.iFunction, _tc.iAddr); } + #define TRACE_ENTRY(string, args...) { if(_tc.Enabled()) _TRACE_PRINT(_TRACE_TEXT(L ## "+ Phonon::MMF::%s [0x%08x] " L ## string), _tc.iFunction, _tc.iAddr, args); } + #define TRACE_EXIT_0() { if(_tc.Enabled()) _TRACE_PRINT(_TRACE_TEXT(L ## "- Phonon::MMF::%s [0x%08x]"), _tc.iFunction, _tc.iAddr); } + #define TRACE_EXIT(string, args...) { if(_tc.Enabled()) _TRACE_PRINT(_TRACE_TEXT(L ## "- Phonon::MMF::%s [0x%08x] " L ## string), _tc.iFunction, _tc.iAddr, args); } + #define TRACE_RETURN(string, result) { if(_tc.Enabled()) _TRACE_PRINT(_TRACE_TEXT(L ## "r Phonon::MMF::%s [0x%08x] " L ## string), _tc.iFunction, _tc.iAddr, result); } return result; + #define TRACE_PANIC(code) { _TRACE_PRINT(_TRACE_TEXT(L ## "! Phonon::MMF::%s [0x%08x] panic %d"), _tc.iFunction, _tc.iAddr, code); } Utils::panic(code); + #define TRACE(string, args...) { if(_tc.Enabled()) _TRACE_PRINT(_TRACE_TEXT(L ## "Phonon::MMF::%s [0x%08x] " L ## string), _tc.iFunction, _tc.iAddr, args); } +#else + #define TRACE_CONTEXT(_fn, _cat) + #define TRACE_ENTRY_0() + #define TRACE_ENTRY(string, args...) + #define TRACE_EXIT_0() + #define TRACE_EXIT(string, args...) + #define TRACE_RETURN(string, result) return result; + #define TRACE_PANIC(code) Utils::panic(code); + #define TRACE(string, args...) +#endif + } +} + +#endif diff --git a/src/plugins/phonon/mmf/mmf.pro b/src/plugins/phonon/mmf/mmf.pro index 6d404f2..ee2d3f9 100644 --- a/src/plugins/phonon/mmf/mmf.pro +++ b/src/plugins/phonon/mmf/mmf.pro @@ -1,17 +1,37 @@ +# MMF Phonon backend + QT += phonon TARGET = phonon_mmf PHONON_MMF_DIR = $$QT_SOURCE_TREE/src/3rdparty/phonon/mmf -LIBS += -lDrmAudioPlayUtility.lib + +# Uncomment the following line in order to use the CDrmPlayerUtility client +# API for audio playback, rather than CMdaAudioPlayerUtility. +#CONFIG += phonon_mmf_audio_drm + +phonon_mmf_audio_drm { + LIBS += -lDrmAudioPlayUtility.lib + + # In the internal 5th SDK, DrmAudioSamplePlayer.h is placed in this + # folder, as opposed to the public, where it is placed in + # epoc32/include. + INCLUDEPATH *= /epoc32/include/osextensions + + DEFINES += QT_PHONON_MMF_AUDIO_DRM +} else { + LIBS += -lmediaclientaudio.lib +} HEADERS += \ $$PHONON_MMF_DIR/audiooutput.h \ $$PHONON_MMF_DIR/backend.h \ - $$PHONON_MMF_DIR/mediaobject.h + $$PHONON_MMF_DIR/mediaobject.h \ + $$PHONON_MMF_DIR/utils.h SOURCES += \ $$PHONON_MMF_DIR/audiooutput.cpp \ $$PHONON_MMF_DIR/backend.cpp \ - $$PHONON_MMF_DIR/mediaobject.cpp + $$PHONON_MMF_DIR/mediaobject.cpp \ + $$PHONON_MMF_DIR/utils.cpp # This is needed for having the .qtplugin file properly created on Symbian. QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/phonon_backend @@ -21,10 +41,6 @@ INSTALLS += target include(../../qpluginbase.pri) -# In the internal 5th SDK, DrmAudioSamplePlayer.h is placed in this folder, as -# opposed to the public, where it is placed in epoc32/include. -INCLUDEPATH *= /epoc32/include/osextensions - # We need this to be able to resolve ambiguity for VideoPlayer.h. Phonon and # the SDK has the header. INCLUDEPATH *= /epoc32 diff --git a/src/plugins/plugins.pro b/src/plugins/plugins.pro index db2e534..004b816 100644 --- a/src/plugins/plugins.pro +++ b/src/plugins/plugins.pro @@ -8,6 +8,7 @@ unix:!symbian { } !embedded:SUBDIRS *= graphicssystems embedded:SUBDIRS *= gfxdrivers decorations mousedrivers kbddrivers +!win32:!embedded:!mac:!symbian:SUBDIRS *= inputmethods symbian:SUBDIRS += s60 contains(QT_CONFIG, phonon): SUBDIRS *= phonon contains(QT_CONFIG, multimedia): SUBDIRS *= audio -- cgit v0.12 From c82bcc8a3bf2ab64db9ccbe7b8ec7ca1208e2edc Mon Sep 17 00:00:00 2001 From: Gareth Stockwell Date: Fri, 14 Aug 2009 13:42:39 +0100 Subject: Fixed a bug which prevented phonon from compiling --- src/3rdparty/phonon/phonon/factory.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/3rdparty/phonon/phonon/factory.cpp b/src/3rdparty/phonon/phonon/factory.cpp index e0b245e..f6e1a5b 100644 --- a/src/3rdparty/phonon/phonon/factory.cpp +++ b/src/3rdparty/phonon/phonon/factory.cpp @@ -133,6 +133,8 @@ bool FactoryPrivate::createBackend() continue; } + QStringList plugins(dir.entryList(QDir::Files)); + #ifdef Q_OS_SYMBIAN /* On Symbian OS we might have two plugins, one which uses Symbian * MMF framework("phonon_mmf"), and one which uses Real Networks's -- cgit v0.12 From 1ef8ddc53d3d2512bbe5afbd2e6fb26cae206944 Mon Sep 17 00:00:00 2001 From: Frans Englich Date: Fri, 14 Aug 2009 15:23:24 +0200 Subject: Pushing compile fix from Gareth, modified by me. Seems this code path was broken. --- src/3rdparty/phonon/phonon/factory.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/3rdparty/phonon/phonon/factory.cpp b/src/3rdparty/phonon/phonon/factory.cpp index e0b245e..b14c2b9 100644 --- a/src/3rdparty/phonon/phonon/factory.cpp +++ b/src/3rdparty/phonon/phonon/factory.cpp @@ -133,6 +133,8 @@ bool FactoryPrivate::createBackend() continue; } + QStringList plugins(dir.entryList(QDir::Files)); + #ifdef Q_OS_SYMBIAN /* On Symbian OS we might have two plugins, one which uses Symbian * MMF framework("phonon_mmf"), and one which uses Real Networks's @@ -140,6 +142,7 @@ bool FactoryPrivate::createBackend() * sophisticated, so we make sure the Helix backend is attempted * to be loaded first, and the MMF backend is used for backup. */ { + const int hxphonon = plugins.indexOf(QLatin1String("hxphonon")); if (hxphonon != -1) plugins.move(hxphonon, 0); @@ -152,9 +155,8 @@ bool FactoryPrivate::createBackend() } #endif - const QStringList files = dir.entryList(QDir::Files); - for (int i = 0; i < files.count(); ++i) { - QPluginLoader pluginLoader(libPath + files.at(i)); + for (int i = 0; i < plugins.count(); ++i) { + QPluginLoader pluginLoader(libPath + plugins.at(i)); if (!pluginLoader.load()) { pDebug() << Q_FUNC_INFO << " load failed:" << pluginLoader.errorString(); -- cgit v0.12 From d10291404e189e3a57cda7fac6f69aa5f9629cae Mon Sep 17 00:00:00 2001 From: Frans Englich Date: Mon, 17 Aug 2009 15:40:04 +0200 Subject: Refactor the media object such that we can do both video and sound. As per discussions with Gareth. --- src/3rdparty/phonon/mmf/abstractplayer.h | 53 +++ src/3rdparty/phonon/mmf/audiooutput.cpp | 2 + src/3rdparty/phonon/mmf/audioplayer.cpp | 631 ++++++++++++++++++++++++++++ src/3rdparty/phonon/mmf/audioplayer.h | 173 ++++++++ src/3rdparty/phonon/mmf/mediaobject.cpp | 499 +--------------------- src/3rdparty/phonon/mmf/mediaobject.h | 102 +---- src/3rdparty/phonon/mmf/mmf_videoplayer.cpp | 577 +++++++++++++++++++++++++ src/3rdparty/phonon/mmf/mmf_videoplayer.h | 163 +++++++ src/plugins/phonon/mmf/mmf.pro | 27 +- 9 files changed, 1618 insertions(+), 609 deletions(-) create mode 100644 src/3rdparty/phonon/mmf/abstractplayer.h create mode 100644 src/3rdparty/phonon/mmf/audioplayer.cpp create mode 100644 src/3rdparty/phonon/mmf/audioplayer.h create mode 100644 src/3rdparty/phonon/mmf/mmf_videoplayer.cpp create mode 100644 src/3rdparty/phonon/mmf/mmf_videoplayer.h diff --git a/src/3rdparty/phonon/mmf/abstractplayer.h b/src/3rdparty/phonon/mmf/abstractplayer.h new file mode 100644 index 0000000..6452090 --- /dev/null +++ b/src/3rdparty/phonon/mmf/abstractplayer.h @@ -0,0 +1,53 @@ +/* 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 . + +*/ + +#ifndef PHONON_MMF_ABSTRACTPLAYER_H +#define PHONON_MMF_ABSTRACTPLAYER_H + +#include +#include +#include + +namespace Phonon +{ + namespace MMF + { + class AbstractPlayer : public QObject + { + public: + virtual void play() = 0; + virtual void pause() = 0; + virtual void stop() = 0; + virtual void seek(qint64 milliseconds) = 0; + virtual qint32 tickInterval() const = 0; + virtual void setTickInterval() const = 0; + virtual bool hasVideo() const = 0; + virtual bool isSeekable() const = 0; + virtual qint64 currentTime() const = 0; + virtual Phonon::State state() const = 0; + virtual QString errorString() const = 0; + virtual Phonon::ErrorType errorType() const = 0; + virtual Phonon::MediaSource source() const = 0; + virtual void setSource(const Phonon::MediaSource &) = 0; + virtual void setNextSource(const Phonon::MediaSource &) = 0; + }; + } +} + +#endif + diff --git a/src/3rdparty/phonon/mmf/audiooutput.cpp b/src/3rdparty/phonon/mmf/audiooutput.cpp index 9c8cb6b..d8758fd 100644 --- a/src/3rdparty/phonon/mmf/audiooutput.cpp +++ b/src/3rdparty/phonon/mmf/audiooutput.cpp @@ -16,6 +16,8 @@ along with this library. If not, see . */ +#include + #include "mediaobject.h" #include "audiooutput.h" #include "utils.h" diff --git a/src/3rdparty/phonon/mmf/audioplayer.cpp b/src/3rdparty/phonon/mmf/audioplayer.cpp new file mode 100644 index 0000000..4dd2eb8 --- /dev/null +++ b/src/3rdparty/phonon/mmf/audioplayer.cpp @@ -0,0 +1,631 @@ +/* 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 . + +*/ + +#include +#include +#include + +#include "audioplayer.h" +#include "audiooutput.h" +#include "utils.h" + +using namespace Phonon; +using namespace Phonon::MMF; + +//----------------------------------------------------------------------------- +// Constants +//----------------------------------------------------------------------------- + +const qint32 DefaultTickInterval = 20; +const int NullMaxVolume = -1; + + +//----------------------------------------------------------------------------- +// Constructor / destructor +//----------------------------------------------------------------------------- + +MMF::AudioPlayer::AudioPlayer(QObject *parent) : m_player(NULL) + , m_audioOutput(NULL) + , m_error(NoError) + , m_state(GroundState) + , m_tickInterval(DefaultTickInterval) + , m_tickTimer(NULL) + , m_volume(0.0) + , m_maxVolume(NullMaxVolume) +{ + TRACE_CONTEXT(AudioPlayer::AudioPlayer, EAudioApi); + TRACE_ENTRY_0(); + + Q_UNUSED(parent); + + // TODO: should leaves be trapped in the constructor? + m_player = CPlayerType::NewL(*this, 0, EMdaPriorityPreferenceNone); + + m_tickTimer = new QTimer(this); + connect(m_tickTimer, SIGNAL(timeout()), this, SLOT(tick())); + + TRACE_EXIT_0(); +} + +MMF::AudioPlayer::~AudioPlayer() +{ + TRACE_CONTEXT(AudioPlayer::~AudioPlayer, EAudioApi); + TRACE_ENTRY_0(); + + delete m_tickTimer; + delete m_player; + + TRACE_EXIT_0(); +} + +//----------------------------------------------------------------------------- +// AudioPlayerInterface +//----------------------------------------------------------------------------- + +void MMF::AudioPlayer::play() +{ + TRACE_CONTEXT(AudioPlayer::play, EAudioApi); + TRACE_ENTRY("state %d", m_state); + + switch(m_state) + { + case GroundState: + case LoadingState: + // Is this the correct error? Really we want 'NotReadyError' + m_error = NormalError; + changeState(ErrorState); + break; + + case StoppedState: + case PausedState: + m_player->Play(); + m_tickTimer->start(m_tickInterval); + changeState(PlayingState); + break; + + case PlayingState: + case BufferingState: + case ErrorState: + // Do nothing + break; + + // Protection against adding new states and forgetting to update this switch + default: + TRACE_PANIC(InvalidStatePanic); + } + + TRACE_EXIT("state %d", m_state); +} + +void MMF::AudioPlayer::pause() +{ + TRACE_CONTEXT(AudioPlayer::pause, EAudioApi); + TRACE_ENTRY("state %d", m_state); + + switch(m_state) + { + case GroundState: + case LoadingState: + case StoppedState: + case PausedState: + case ErrorState: + // Do nothing + break; + + case PlayingState: + case BufferingState: + m_player->Pause(); + m_tickTimer->stop(); + changeState(PausedState); + break; + + // Protection against adding new states and forgetting to update this switch + default: + TRACE_PANIC(InvalidStatePanic); + } + + TRACE_EXIT("state %d", m_state); +} + +void MMF::AudioPlayer::stop() +{ + TRACE_CONTEXT(AudioPlayer::stop, EAudioApi); + TRACE_ENTRY("state %d", m_state); + + switch(m_state) + { + case GroundState: + case LoadingState: + case StoppedState: + case ErrorState: + // Do nothing + break; + + case PlayingState: + case BufferingState: + case PausedState: + m_player->Stop(); + m_tickTimer->stop(); + changeState(StoppedState); + break; + + // Protection against adding new states and forgetting to update this switch + default: + TRACE_PANIC(InvalidStatePanic); + } + + TRACE_EXIT("state %d", m_state); +} + +void MMF::AudioPlayer::seek(qint64 ms) +{ + TRACE_CONTEXT(AudioPlayer::seek, EAudioApi); + TRACE_ENTRY("state %d pos %Ld", m_state, ms); + + m_player->SetPosition(TTimeIntervalMicroSeconds(ms)); + + TRACE_EXIT_0(); +} + +qint32 MMF::AudioPlayer::tickInterval() const +{ + TRACE_CONTEXT(AudioPlayer::tickInterval, EAudioApi); + TRACE_ENTRY("state %d", m_state); + + TRACE_RETURN("%d", m_tickInterval); +} + +void MMF::AudioPlayer::setTickInterval(qint32 interval) +{ + TRACE_CONTEXT(AudioPlayer::setTickInterval, EAudioApi); + TRACE_ENTRY("state %d m_interval %d interval %d", m_state, m_tickInterval, interval); + + m_tickInterval = interval; + m_tickTimer->setInterval(interval); + + TRACE_EXIT_0(); +} + +bool MMF::AudioPlayer::hasVideo() const +{ + TRACE_CONTEXT(AudioPlayer::hasVideo, EAudioApi); + TRACE_ENTRY("state %d", m_state); + + // TODO: re-factor this class so that audio playback and video playback are + // delegated to separate classes, which internally hoat a + // CMdaAudioPlayerUtility / CVideoPlayerUtility instance as appropriate. + + TRACE_RETURN("%d", false); +} + +bool MMF::AudioPlayer::isSeekable() const +{ + TRACE_CONTEXT(AudioPlayer::isSeekable, EAudioApi); + TRACE_ENTRY("state %d", m_state); + + TRACE_RETURN("%d", true); +} + +Phonon::State MMF::AudioPlayer::state() const +{ + TRACE_CONTEXT(AudioPlayer::state, EAudioApi); + TRACE_ENTRY("state %d", m_state); + + const Phonon::State result = phononState(m_state); + + TRACE_RETURN("%d", result); +} + +qint64 MMF::AudioPlayer::currentTime() const +{ + TRACE_CONTEXT(AudioPlayer::currentTime, EAudioApi); + TRACE_ENTRY("state %d", m_state); + + TTimeIntervalMicroSeconds us; + const TInt err = m_player->GetPosition(us); + + qint64 result = -1; + + if(KErrNone == err) { + result = toMilliSeconds(us); + } + + TRACE_RETURN("%Ld", result); +} + +QString MMF::AudioPlayer::errorString() const +{ + TRACE_CONTEXT(AudioPlayer::errorString, EAudioApi); + TRACE_ENTRY("state %d", m_state); + + TRACE_EXIT_0(); + // TODO: put in proper error strings + QString result; + return result; +} + +Phonon::ErrorType MMF::AudioPlayer::errorType() const +{ + TRACE_CONTEXT(AudioPlayer::errorType, EAudioApi); + TRACE_ENTRY("state %d", m_state); + + const Phonon::ErrorType result = (ErrorState == m_state) + ? m_error : NoError; + + TRACE_RETURN("%d", result); +} + +qint64 MMF::AudioPlayer::totalTime() const +{ + TRACE_CONTEXT(AudioPlayer::totalTime, EAudioApi); + TRACE_ENTRY("state %d", m_state); + + const qint64 result = toMilliSeconds(m_player->Duration()); + + TRACE_RETURN("%Ld", result); +} + +MediaSource MMF::AudioPlayer::source() const +{ + TRACE_CONTEXT(AudioPlayer::source, EAudioApi); + TRACE_ENTRY("state %d", m_state); + + TRACE_EXIT_0(); + return m_mediaSource; +} + +void MMF::AudioPlayer::setSource(const MediaSource &source) +{ + TRACE_CONTEXT(AudioPlayer::setSource, EAudioApi); + TRACE_ENTRY("state %d source.type %d", m_state, source.type()); + + m_player->Close(); + changeState(GroundState); + + // TODO: is it correct to assign even if the media type is not supported in + // the switch statement below? + m_mediaSource = source; + + TInt symbianErr = KErrNone; + + switch(m_mediaSource.type()) + { + case MediaSource::LocalFile: + { + // TODO: work out whose responsibility it is to ensure that paths + // are Symbian-style, i.e. have backslashes for path delimiters. + // Until then, use this utility function... + const QHBufC filename = Utils::symbianFilename(m_mediaSource.fileName()); + TRAP(symbianErr, m_player->OpenFileL(*filename)); + break; + } + + case MediaSource::Url: + { + const QHBufC filename(m_mediaSource.url().toString()); + TRAP(symbianErr, m_player->OpenUrlL(*filename)); + break; + } + + case MediaSource::Invalid: + case MediaSource::Disc: + case MediaSource::Stream: + symbianErr = KErrNotSupported; + break; + + case MediaSource::Empty: + TRACE_EXIT_0(); + return; + + // Protection against adding new media types and forgetting to update this switch + default: + TRACE_PANIC(InvalidMediaTypePanic); + } + + if(KErrNone == symbianErr) + { +#ifdef QT_PHONON_MMF_AUDIO_DRM + // There appears to be a bug in the CDrmPlayerUtility implementation (at least + // in S60 5.x) whereby the player does not check whether the loading observer + // pointer is null before dereferencing it. Therefore we must register for + // loading notification, even though we do nothing in the callback functions. + m_player->RegisterForAudioLoadingNotification(*this); +#endif + changeState(LoadingState); + } + else + { + // TODO: do something with the value of symbianErr? + m_error = NormalError; + changeState(ErrorState); + } + + TRACE_EXIT_0(); +} + +void MMF::AudioPlayer::setNextSource(const MediaSource &source) +{ + TRACE_CONTEXT(AudioPlayer::setNextSource, EAudioApi); + TRACE_ENTRY("state %d", m_state); + + // TODO: handle 'next source' + + m_nextSource = source; + Q_UNUSED(source); + + TRACE_EXIT_0(); +} + +qint32 MMF::AudioPlayer::prefinishMark() const +{ + TRACE_CONTEXT(AudioPlayer::prefinishMark, EAudioApi); + TRACE_ENTRY("state %d", m_state); + + // TODO: implement prefinish mark + const qint32 result = 0; + TRACE_RETURN("%d", result); +} + +void MMF::AudioPlayer::setPrefinishMark(qint32 mark) +{ + TRACE_CONTEXT(AudioPlayer::setPrefinishMark, EAudioApi); + TRACE_ENTRY("state %d mark %d", m_state, mark); + Q_UNUSED(mark); // to silence warnings in release builds + + // TODO: implement prefinish mark + + TRACE_EXIT_0(); +} + +qint32 MMF::AudioPlayer::transitionTime() const +{ + TRACE_CONTEXT(AudioPlayer::transitionTime, EAudioApi); + TRACE_ENTRY("state %d", m_state); + + // TODO: implement transition time + const qint32 result = 0; + TRACE_RETURN("%d", result); +} + +void MMF::AudioPlayer::setTransitionTime(qint32 time) +{ + TRACE_CONTEXT(AudioPlayer::setTransitionTime, EAudioApi); + TRACE_ENTRY("state %d time %d", m_state, time); + Q_UNUSED(time); // to silence warnings in release builds + + // TODO: implement transition time + + TRACE_EXIT_0(); +} + + +//----------------------------------------------------------------------------- +// Symbian multimedia client observer callbacks +//----------------------------------------------------------------------------- + +#ifdef QT_PHONON_MMF_AUDIO_DRM +void MMF::AudioPlayer::MdapcInitComplete(TInt aError, + const TTimeIntervalMicroSeconds &) +#else +void MMF::AudioPlayer::MapcInitComplete(TInt aError, + const TTimeIntervalMicroSeconds &) +#endif +{ + TRACE_CONTEXT(AudioPlayer::MapcInitComplete, EAudioInternal); + TRACE_ENTRY("state %d error %d", m_state, aError); + + __ASSERT_ALWAYS(LoadingState == m_state, Utils::panic(InvalidStatePanic)); + + if(KErrNone == aError) + { + TInt volume = 0; + aError = m_player->GetVolume(volume); + if(KErrNone == aError) + { + m_maxVolume = m_player->MaxVolume(); + m_volume = static_cast(volume) / m_maxVolume; + + if(m_audioOutput) + { + // Trigger AudioOutput signal + m_audioOutput->triggerVolumeChanged(m_volume); + } + + emit totalTimeChanged(); + changeState(StoppedState); + } + } + else + { + // TODO: set different error states according to value of aError? + m_error = NormalError; + changeState(ErrorState); + } + + TRACE_EXIT_0(); +} + +#ifdef QT_PHONON_MMF_AUDIO_DRM +void MMF::AudioPlayer::MdapcPlayComplete(TInt aError) +#else +void MMF::AudioPlayer::MapcPlayComplete(TInt aError) +#endif +{ + TRACE_CONTEXT(AudioPlayer::MapcPlayComplete, EAudioInternal); + TRACE_ENTRY("state %d error %d", m_state, aError); + + m_tickTimer->stop(); + + if(KErrNone == aError) + { + changeState(StoppedState); + // TODO: move on to m_nextSource + } + else + { + // TODO: do something with aError? + m_error = NormalError; + changeState(ErrorState); + } + +/* + 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); + } +*/ + + TRACE_EXIT_0(); +} + +#ifdef QT_PHONON_MMF_AUDIO_DRM +void MMF::AudioPlayer::MaloLoadingStarted() +{ + +} + +void MMF::AudioPlayer::MaloLoadingComplete() +{ + +} +#endif // QT_PHONON_MMF_AUDIO_DRM + + +//----------------------------------------------------------------------------- +// Volume +//----------------------------------------------------------------------------- + +qreal MMF::AudioPlayer::volume() const +{ + return m_volume; +} + +bool MMF::AudioPlayer::setVolume(qreal volume) +{ + TRACE_CONTEXT(AudioPlayer::setVolume, EAudioInternal); + TRACE_ENTRY("state %d", m_state); + + bool volumeChanged = false; + + switch(m_state) + { + case GroundState: + case LoadingState: + case ErrorState: + // Do nothing + break; + + case StoppedState: + case PausedState: + case PlayingState: + case BufferingState: + { + if(volume != m_volume) + { + const int err = m_player->SetVolume(volume * m_maxVolume); + if(KErrNone == err) + { + m_volume = volume; + volumeChanged = true; + } + else + { + m_error = NormalError; + changeState(ErrorState); + } + } + break; + } + + // Protection against adding new states and forgetting to update this + // switch + default: + TRACE_PANIC(InvalidStatePanic); + } + + TRACE_RETURN("%d", volumeChanged); +} + +void MMF::AudioPlayer::setAudioOutput(AudioOutput* audioOutput) +{ + m_audioOutput = audioOutput; +} + + +//----------------------------------------------------------------------------- +// Private functions +//----------------------------------------------------------------------------- + +qint64 MMF::AudioPlayer::toMilliSeconds(const TTimeIntervalMicroSeconds &in) +{ + return in.Int64() / 1000; +} + +Phonon::State MMF::AudioPlayer::phononState(PrivateState state) +{ + const Phonon::State phononState = + GroundState == state + ? Phonon::StoppedState + : static_cast(state); + + return phononState; +} + +void MMF::AudioPlayer::changeState(PrivateState newState) +{ + TRACE_CONTEXT(AudioPlayer::changeState, EAudioInternal); + TRACE_ENTRY("state %d newState %d", m_state, newState); + + // TODO: add some invariants to check that the transition is valid + + const Phonon::State currentPhononState = phononState(m_state); + const Phonon::State newPhononState = phononState(newState); + if(currentPhononState != newPhononState) + { + TRACE("emit stateChanged(%d, %d)", newPhononState, currentPhononState); + emit stateChanged(newPhononState, currentPhononState); + } + + m_state = newState; + + TRACE_EXIT_0(); +} + +void MMF::AudioPlayer::tick() +{ + TRACE_CONTEXT(AudioPlayer::tick, EAudioInternal); + TRACE_ENTRY("state %d", m_state); + + emit tick(currentTime()); + + TRACE_EXIT_0(); +} + + + + diff --git a/src/3rdparty/phonon/mmf/audioplayer.h b/src/3rdparty/phonon/mmf/audioplayer.h new file mode 100644 index 0000000..d9a64e1 --- /dev/null +++ b/src/3rdparty/phonon/mmf/audioplayer.h @@ -0,0 +1,173 @@ +/* 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 . + +*/ + +#ifndef PHONON_MMF_AUDIOPLAYER_H +#define PHONON_MMF_AUDIOPLAYER_H + +#include "abstractplayer.h" + +class CDrmPlayerUtility; +class TTimeIntervalMicroSeconds; +class QTimer; + +#ifdef QT_PHONON_MMF_AUDIO_DRM +#include +typedef CDrmPlayerUtility CPlayerType; +typedef MDrmAudioPlayerCallback MPlayerObserverType; +#else +#include +typedef CMdaAudioPlayerUtility CPlayerType; +typedef MMdaAudioPlayerCallback MPlayerObserverType; +#endif + +namespace Phonon +{ + namespace MMF + { + class AudioOutput; + + /** + * + * See + * How to + * play a video file using CVideoPlayerUtility + */ + class AudioPlayer : public AbstractPlayer + , public MPlayerObserverType // typedef +#ifdef QT_PHONON_MMF_AUDIO_DRM + , public MAudioLoadingObserver +#endif + { + Q_OBJECT + + public: + AudioPlayer(QObject *parent); + virtual ~AudioPlayer(); + + // AbstractPlayer + virtual void play(); + virtual void pause(); + virtual void stop(); + virtual void seek(qint64 milliseconds); + virtual qint32 tickInterval() const; + virtual void setTickInterval(qint32 interval); + virtual bool hasVideo() const; + virtual bool isSeekable() const; + virtual qint64 currentTime() const; + virtual Phonon::State state() const; + virtual QString errorString() const; + virtual Phonon::ErrorType errorType() const; + virtual qint64 totalTime() const; + virtual MediaSource source() const; + virtual void setSource(const MediaSource &); + virtual void setNextSource(const MediaSource &source); + virtual qint32 prefinishMark() const; + virtual void setPrefinishMark(qint32); + virtual qint32 transitionTime() const; + virtual void setTransitionTime(qint32); + +#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, + const TTimeIntervalMicroSeconds &aDuration); + virtual void MapcPlayComplete(TInt aError); +#endif + + qreal volume() const; + bool setVolume(qreal volume); + + void setAudioOutput(AudioOutput* audioOutput); + + Q_SIGNALS: + void totalTimeChanged(); + void stateChanged(Phonon::State oldState, + Phonon::State newState); + void finished(); + void tick(qint64 time); + + private Q_SLOTS: + /** + * Receives signal from m_tickTimer + */ + void tick(); + + private: + static qint64 toMilliSeconds(const TTimeIntervalMicroSeconds &); + + /** + * Defined private state enumeration in order to add GroundState + */ + enum PrivateState + { + LoadingState = Phonon::LoadingState, + StoppedState = Phonon::StoppedState, + PlayingState = Phonon::PlayingState, + BufferingState = Phonon::BufferingState, + PausedState = Phonon::PausedState, + ErrorState = Phonon::ErrorState, + GroundState + }; + + /** + * Converts PrivateState into the corresponding Phonon::State + */ + static Phonon::State phononState(PrivateState state); + + /** + * Changes state and emits stateChanged() + */ + void changeState(PrivateState newState); + + /** + * Using CPlayerType typedef in order to be able to easily switch between + * CMdaAudioPlayerUtility and CDrmPlayerUtility + */ + CPlayerType* m_player; + + AudioOutput* m_audioOutput; + + ErrorType m_error; + + /** + * Do not set this directly - call changeState() instead. + */ + PrivateState m_state; + + qint32 m_tickInterval; + + QTimer* m_tickTimer; + + MediaSource m_mediaSource; + MediaSource m_nextSource; + + qreal m_volume; + int m_maxVolume; + }; + } +} + +#endif diff --git a/src/3rdparty/phonon/mmf/mediaobject.cpp b/src/3rdparty/phonon/mmf/mediaobject.cpp index 8a4b76e..fb079f0 100644 --- a/src/3rdparty/phonon/mmf/mediaobject.cpp +++ b/src/3rdparty/phonon/mmf/mediaobject.cpp @@ -16,61 +16,21 @@ along with this library. If not, see . */ -#include -#include -#include - #include "mediaobject.h" -#include "audiooutput.h" -#include "utils.h" using namespace Phonon; using namespace Phonon::MMF; //----------------------------------------------------------------------------- -// Constants -//----------------------------------------------------------------------------- - -const qint32 DefaultTickInterval = 20; -const int NullMaxVolume = -1; - - -//----------------------------------------------------------------------------- // Constructor / destructor //----------------------------------------------------------------------------- -MMF::MediaObject::MediaObject(QObject *parent) : m_player(NULL) - , m_audioOutput(NULL) - , m_error(NoError) - , m_state(GroundState) - , m_tickInterval(DefaultTickInterval) - , m_tickTimer(NULL) - , m_volume(0.0) - , m_maxVolume(NullMaxVolume) +MMF::MediaObject::MediaObject(QObject *parent) : QObject::QObject(parent) { - TRACE_CONTEXT(MediaObject::MediaObject, EAudioApi); - TRACE_ENTRY_0(); - - Q_UNUSED(parent); - - // TODO: should leaves be trapped in the constructor? - m_player = CPlayerType::NewL(*this, 0, EMdaPriorityPreferenceNone); - - m_tickTimer = new QTimer(this); - connect(m_tickTimer, SIGNAL(timeout()), this, SLOT(tick())); - - TRACE_EXIT_0(); } MMF::MediaObject::~MediaObject() { - TRACE_CONTEXT(MediaObject::~MediaObject, EAudioApi); - TRACE_ENTRY_0(); - - delete m_tickTimer; - delete m_player; - - TRACE_EXIT_0(); } //----------------------------------------------------------------------------- @@ -79,442 +39,84 @@ MMF::MediaObject::~MediaObject() void MMF::MediaObject::play() { - TRACE_CONTEXT(MediaObject::play, EAudioApi); - TRACE_ENTRY("state %d", m_state); - - switch(m_state) - { - case GroundState: - case LoadingState: - // Is this the correct error? Really we want 'NotReadyError' - m_error = NormalError; - changeState(ErrorState); - break; - - case StoppedState: - case PausedState: - m_player->Play(); - m_tickTimer->start(m_tickInterval); - changeState(PlayingState); - break; - - case PlayingState: - case BufferingState: - case ErrorState: - // Do nothing - break; - - // Protection against adding new states and forgetting to update this switch - default: - TRACE_PANIC(InvalidStatePanic); - } - - TRACE_EXIT("state %d", m_state); } void MMF::MediaObject::pause() { - TRACE_CONTEXT(MediaObject::pause, EAudioApi); - TRACE_ENTRY("state %d", m_state); - - switch(m_state) - { - case GroundState: - case LoadingState: - case StoppedState: - case PausedState: - case ErrorState: - // Do nothing - break; - - case PlayingState: - case BufferingState: - m_player->Pause(); - m_tickTimer->stop(); - changeState(PausedState); - break; - - // Protection against adding new states and forgetting to update this switch - default: - TRACE_PANIC(InvalidStatePanic); - } - - TRACE_EXIT("state %d", m_state); } void MMF::MediaObject::stop() { - TRACE_CONTEXT(MediaObject::stop, EAudioApi); - TRACE_ENTRY("state %d", m_state); - - switch(m_state) - { - case GroundState: - case LoadingState: - case StoppedState: - case ErrorState: - // Do nothing - break; - - case PlayingState: - case BufferingState: - case PausedState: - m_player->Stop(); - m_tickTimer->stop(); - changeState(StoppedState); - break; - - // Protection against adding new states and forgetting to update this switch - default: - TRACE_PANIC(InvalidStatePanic); - } - - TRACE_EXIT("state %d", m_state); } void MMF::MediaObject::seek(qint64 ms) { - TRACE_CONTEXT(MediaObject::seek, EAudioApi); - TRACE_ENTRY("state %d pos %Ld", m_state, ms); - - m_player->SetPosition(TTimeIntervalMicroSeconds(ms)); - - TRACE_EXIT_0(); + Q_UNUSED(ms); } qint32 MMF::MediaObject::tickInterval() const { - TRACE_CONTEXT(MediaObject::tickInterval, EAudioApi); - TRACE_ENTRY("state %d", m_state); - - TRACE_RETURN("%d", m_tickInterval); } void MMF::MediaObject::setTickInterval(qint32 interval) { - TRACE_CONTEXT(MediaObject::setTickInterval, EAudioApi); - TRACE_ENTRY("state %d m_interval %d interval %d", m_state, m_tickInterval, interval); - - m_tickInterval = interval; - m_tickTimer->setInterval(interval); - - TRACE_EXIT_0(); } bool MMF::MediaObject::hasVideo() const { - TRACE_CONTEXT(MediaObject::hasVideo, EAudioApi); - TRACE_ENTRY("state %d", m_state); - - // TODO: re-factor this class so that audio playback and video playback are - // delegated to separate classes, which internally hoat a - // CMdaAudioPlayerUtility / CVideoPlayerUtility instance as appropriate. - - TRACE_RETURN("%d", false); } bool MMF::MediaObject::isSeekable() const { - TRACE_CONTEXT(MediaObject::isSeekable, EAudioApi); - TRACE_ENTRY("state %d", m_state); - - TRACE_RETURN("%d", true); } Phonon::State MMF::MediaObject::state() const { - TRACE_CONTEXT(MediaObject::state, EAudioApi); - TRACE_ENTRY("state %d", m_state); - - const Phonon::State result = phononState(m_state); - - TRACE_RETURN("%d", result); } qint64 MMF::MediaObject::currentTime() const { - TRACE_CONTEXT(MediaObject::currentTime, EAudioApi); - TRACE_ENTRY("state %d", m_state); - - TTimeIntervalMicroSeconds us; - const TInt err = m_player->GetPosition(us); - - qint64 result = -1; - - if(KErrNone == err) { - result = toMilliSeconds(us); - } - - TRACE_RETURN("%Ld", result); } QString MMF::MediaObject::errorString() const { - TRACE_CONTEXT(MediaObject::errorString, EAudioApi); - TRACE_ENTRY("state %d", m_state); - - TRACE_EXIT_0(); - // TODO: put in proper error strings - QString result; - return result; } Phonon::ErrorType MMF::MediaObject::errorType() const { - TRACE_CONTEXT(MediaObject::errorType, EAudioApi); - TRACE_ENTRY("state %d", m_state); - - const Phonon::ErrorType result = (ErrorState == m_state) - ? m_error : NoError; - - TRACE_RETURN("%d", result); } qint64 MMF::MediaObject::totalTime() const { - TRACE_CONTEXT(MediaObject::totalTime, EAudioApi); - TRACE_ENTRY("state %d", m_state); - - const qint64 result = toMilliSeconds(m_player->Duration()); - - TRACE_RETURN("%Ld", result); } MediaSource MMF::MediaObject::source() const { - TRACE_CONTEXT(MediaObject::source, EAudioApi); - TRACE_ENTRY("state %d", m_state); - - TRACE_EXIT_0(); - return m_mediaSource; } void MMF::MediaObject::setSource(const MediaSource &source) { - TRACE_CONTEXT(MediaObject::setSource, EAudioApi); - TRACE_ENTRY("state %d source.type %d", m_state, source.type()); - - m_player->Close(); - changeState(GroundState); - - // TODO: is it correct to assign even if the media type is not supported in - // the switch statement below? - m_mediaSource = source; - - TInt symbianErr = KErrNone; - - switch(m_mediaSource.type()) - { - case MediaSource::LocalFile: - { - // TODO: work out whose responsibility it is to ensure that paths - // are Symbian-style, i.e. have backslashes for path delimiters. - // Until then, use this utility function... - const QHBufC filename = Utils::symbianFilename(m_mediaSource.fileName()); - TRAP(symbianErr, m_player->OpenFileL(*filename)); - break; - } - - case MediaSource::Url: - { - const QHBufC filename(m_mediaSource.url().toString()); - TRAP(symbianErr, m_player->OpenUrlL(*filename)); - break; - } - - case MediaSource::Invalid: - case MediaSource::Disc: - case MediaSource::Stream: - symbianErr = KErrNotSupported; - break; - - case MediaSource::Empty: - TRACE_EXIT_0(); - return; - - // Protection against adding new media types and forgetting to update this switch - default: - TRACE_PANIC(InvalidMediaTypePanic); - } - - if(KErrNone == symbianErr) - { -#ifdef QT_PHONON_MMF_AUDIO_DRM - // There appears to be a bug in the CDrmPlayerUtility implementation (at least - // in S60 5.x) whereby the player does not check whether the loading observer - // pointer is null before dereferencing it. Therefore we must register for - // loading notification, even though we do nothing in the callback functions. - m_player->RegisterForAudioLoadingNotification(*this); -#endif - changeState(LoadingState); - } - else - { - // TODO: do something with the value of symbianErr? - m_error = NormalError; - changeState(ErrorState); - } - - TRACE_EXIT_0(); } void MMF::MediaObject::setNextSource(const MediaSource &source) { - TRACE_CONTEXT(MediaObject::setNextSource, EAudioApi); - TRACE_ENTRY("state %d", m_state); - - // TODO: handle 'next source' - - m_nextSource = source; - Q_UNUSED(source); - - TRACE_EXIT_0(); } qint32 MMF::MediaObject::prefinishMark() const { - TRACE_CONTEXT(MediaObject::prefinishMark, EAudioApi); - TRACE_ENTRY("state %d", m_state); - - // TODO: implement prefinish mark - const qint32 result = 0; - TRACE_RETURN("%d", result); } void MMF::MediaObject::setPrefinishMark(qint32 mark) { - TRACE_CONTEXT(MediaObject::setPrefinishMark, EAudioApi); - TRACE_ENTRY("state %d mark %d", m_state, mark); - Q_UNUSED(mark); // to silence warnings in release builds - - // TODO: implement prefinish mark - - TRACE_EXIT_0(); } qint32 MMF::MediaObject::transitionTime() const { - TRACE_CONTEXT(MediaObject::transitionTime, EAudioApi); - TRACE_ENTRY("state %d", m_state); - - // TODO: implement transition time - const qint32 result = 0; - TRACE_RETURN("%d", result); } void MMF::MediaObject::setTransitionTime(qint32 time) { - TRACE_CONTEXT(MediaObject::setTransitionTime, EAudioApi); - TRACE_ENTRY("state %d time %d", m_state, time); - Q_UNUSED(time); // to silence warnings in release builds - - // TODO: implement transition time - - TRACE_EXIT_0(); -} - - -//----------------------------------------------------------------------------- -// Symbian multimedia client observer callbacks -//----------------------------------------------------------------------------- - -#ifdef QT_PHONON_MMF_AUDIO_DRM -void MMF::MediaObject::MdapcInitComplete(TInt aError, - const TTimeIntervalMicroSeconds &) -#else -void MMF::MediaObject::MapcInitComplete(TInt aError, - const TTimeIntervalMicroSeconds &) -#endif -{ - TRACE_CONTEXT(MediaObject::MapcInitComplete, EAudioInternal); - TRACE_ENTRY("state %d error %d", m_state, aError); - - __ASSERT_ALWAYS(LoadingState == m_state, Utils::panic(InvalidStatePanic)); - - if(KErrNone == aError) - { - TInt volume = 0; - aError = m_player->GetVolume(volume); - if(KErrNone == aError) - { - m_maxVolume = m_player->MaxVolume(); - m_volume = static_cast(volume) / m_maxVolume; - - if(m_audioOutput) - { - // Trigger AudioOutput signal - m_audioOutput->triggerVolumeChanged(m_volume); - } - - emit totalTimeChanged(); - changeState(StoppedState); - } - } - else - { - // TODO: set different error states according to value of aError? - m_error = NormalError; - changeState(ErrorState); - } - - TRACE_EXIT_0(); -} - -#ifdef QT_PHONON_MMF_AUDIO_DRM -void MMF::MediaObject::MdapcPlayComplete(TInt aError) -#else -void MMF::MediaObject::MapcPlayComplete(TInt aError) -#endif -{ - TRACE_CONTEXT(MediaObject::MapcPlayComplete, EAudioInternal); - TRACE_ENTRY("state %d error %d", m_state, aError); - - m_tickTimer->stop(); - - if(KErrNone == aError) - { - changeState(StoppedState); - // TODO: move on to m_nextSource - } - else - { - // TODO: do something with aError? - m_error = NormalError; - changeState(ErrorState); - } - -/* - 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); - } -*/ - - TRACE_EXIT_0(); -} - -#ifdef QT_PHONON_MMF_AUDIO_DRM -void MMF::MediaObject::MaloLoadingStarted() -{ - -} - -void MMF::MediaObject::MaloLoadingComplete() -{ - } -#endif // QT_PHONON_MMF_AUDIO_DRM - //----------------------------------------------------------------------------- // Volume @@ -522,110 +124,13 @@ void MMF::MediaObject::MaloLoadingComplete() qreal MMF::MediaObject::volume() const { - return m_volume; } bool MMF::MediaObject::setVolume(qreal volume) { - TRACE_CONTEXT(MediaObject::setVolume, EAudioInternal); - TRACE_ENTRY("state %d", m_state); - - bool volumeChanged = false; - - switch(m_state) - { - case GroundState: - case LoadingState: - case ErrorState: - // Do nothing - break; - - case StoppedState: - case PausedState: - case PlayingState: - case BufferingState: - { - if(volume != m_volume) - { - const int err = m_player->SetVolume(volume * m_maxVolume); - if(KErrNone == err) - { - m_volume = volume; - volumeChanged = true; - } - else - { - m_error = NormalError; - changeState(ErrorState); - } - } - break; - } - - // Protection against adding new states and forgetting to update this - // switch - default: - TRACE_PANIC(InvalidStatePanic); - } - - TRACE_RETURN("%d", volumeChanged); } void MMF::MediaObject::setAudioOutput(AudioOutput* audioOutput) { - m_audioOutput = audioOutput; -} - - -//----------------------------------------------------------------------------- -// Private functions -//----------------------------------------------------------------------------- - -qint64 MMF::MediaObject::toMilliSeconds(const TTimeIntervalMicroSeconds &in) -{ - return in.Int64() / 1000; -} - -Phonon::State MMF::MediaObject::phononState(PrivateState state) -{ - const Phonon::State phononState = - GroundState == state - ? Phonon::StoppedState - : static_cast(state); - - return phononState; -} - -void MMF::MediaObject::changeState(PrivateState newState) -{ - TRACE_CONTEXT(MediaObject::changeState, EAudioInternal); - TRACE_ENTRY("state %d newState %d", m_state, newState); - - // TODO: add some invariants to check that the transition is valid - - const Phonon::State currentPhononState = phononState(m_state); - const Phonon::State newPhononState = phononState(newState); - if(currentPhononState != newPhononState) - { - TRACE("emit stateChanged(%d, %d)", newPhononState, currentPhononState); - emit stateChanged(newPhononState, currentPhononState); - } - - m_state = newState; - - TRACE_EXIT_0(); -} - -void MMF::MediaObject::tick() -{ - TRACE_CONTEXT(MediaObject::tick, EAudioInternal); - TRACE_ENTRY("state %d", m_state); - - emit tick(currentTime()); - - TRACE_EXIT_0(); } - - - diff --git a/src/3rdparty/phonon/mmf/mediaobject.h b/src/3rdparty/phonon/mmf/mediaobject.h index f17580e..d162455 100644 --- a/src/3rdparty/phonon/mmf/mediaobject.h +++ b/src/3rdparty/phonon/mmf/mediaobject.h @@ -19,26 +19,8 @@ along with this library. If not, see . #ifndef PHONON_MMF_MEDIAOBJECT_H #define PHONON_MMF_MEDIAOBJECT_H -/* We use the extra qualification include/ to avoid picking up the include - * Phonon has. */ -#include - #include -#include - -class CDrmPlayerUtility; -class TTimeIntervalMicroSeconds; -class QTimer; - -#ifdef QT_PHONON_MMF_AUDIO_DRM -#include -typedef CDrmPlayerUtility CPlayerType; -typedef MDrmAudioPlayerCallback MPlayerObserverType; -#else -#include -typedef CMdaAudioPlayerUtility CPlayerType; -typedef MMdaAudioPlayerCallback MPlayerObserverType; -#endif +#include namespace Phonon { @@ -47,17 +29,9 @@ namespace Phonon class AudioOutput; /** - * - * See - * How to - * play a video file using CVideoPlayerUtility */ class MediaObject : public QObject , public MediaObjectInterface - , public MPlayerObserverType // typedef -#ifdef QT_PHONON_MMF_AUDIO_DRM - , public MAudioLoadingObserver -#endif { Q_OBJECT Q_INTERFACES(Phonon::MediaObjectInterface) @@ -88,22 +62,6 @@ namespace Phonon virtual qint32 transitionTime() const; virtual void setTransitionTime(qint32); -#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, - const TTimeIntervalMicroSeconds &aDuration); - virtual void MapcPlayComplete(TInt aError); -#endif - qreal volume() const; bool setVolume(qreal volume); @@ -115,64 +73,6 @@ namespace Phonon Phonon::State newState); void finished(); void tick(qint64 time); - - private Q_SLOTS: - /** - * Receives signal from m_tickTimer - */ - void tick(); - - private: - static qint64 toMilliSeconds(const TTimeIntervalMicroSeconds &); - - /** - * Defined private state enumeration in order to add GroundState - */ - enum PrivateState - { - LoadingState = Phonon::LoadingState, - StoppedState = Phonon::StoppedState, - PlayingState = Phonon::PlayingState, - BufferingState = Phonon::BufferingState, - PausedState = Phonon::PausedState, - ErrorState = Phonon::ErrorState, - GroundState - }; - - /** - * Converts PrivateState into the corresponding Phonon::State - */ - static Phonon::State phononState(PrivateState state); - - /** - * Changes state and emits stateChanged() - */ - void changeState(PrivateState newState); - - /** - * Using CPlayerType typedef in order to be able to easily switch between - * CMdaAudioPlayerUtility and CDrmPlayerUtility - */ - CPlayerType* m_player; - - AudioOutput* m_audioOutput; - - ErrorType m_error; - - /** - * Do not set this directly - call changeState() instead. - */ - PrivateState m_state; - - qint32 m_tickInterval; - - QTimer* m_tickTimer; - - MediaSource m_mediaSource; - MediaSource m_nextSource; - - qreal m_volume; - int m_maxVolume; }; } } diff --git a/src/3rdparty/phonon/mmf/mmf_videoplayer.cpp b/src/3rdparty/phonon/mmf/mmf_videoplayer.cpp new file mode 100644 index 0000000..3a51070 --- /dev/null +++ b/src/3rdparty/phonon/mmf/mmf_videoplayer.cpp @@ -0,0 +1,577 @@ +/* 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 . + +*/ + +#include +#include +#include + +#include "mmf_videoplayer.h" +#include "audiooutput.h" +#include "utils.h" + +using namespace Phonon; +using namespace Phonon::MMF; + +//----------------------------------------------------------------------------- +// Constants +//----------------------------------------------------------------------------- + +const qint32 DefaultTickInterval = 20; +const int NullMaxVolume = -1; + + +//----------------------------------------------------------------------------- +// Constructor / destructor +//----------------------------------------------------------------------------- + +MMF::VideoPlayer::VideoPlayer(QObject *parent) : m_audioOutput(NULL) + , m_error(NoError) + , m_state(GroundState) + , m_tickInterval(DefaultTickInterval) + , m_tickTimer(NULL) + , m_volume(0.0) + , m_maxVolume(NullMaxVolume) +{ +#if 0 + TRACE_CONTEXT(VideoPlayer::VideoPlayer, EAudioApi); + TRACE_ENTRY_0(); + + Q_UNUSED(parent); + + // TODO: should leaves be trapped in the constructor? + m_player = CPlayerType::NewL(*this, 0, EMdaPriorityPreferenceNone); + + m_tickTimer = new QTimer(this); + connect(m_tickTimer, SIGNAL(timeout()), this, SLOT(tick())); + + TRACE_EXIT_0(); +#endif +} + +MMF::VideoPlayer::~VideoPlayer() +{ +#if 0 + TRACE_CONTEXT(VideoPlayer::~VideoPlayer, EAudioApi); + TRACE_ENTRY_0(); + + delete m_tickTimer; + delete m_player; + + TRACE_EXIT_0(); +#endif +} + +//----------------------------------------------------------------------------- +// VideoPlayerInterface +//----------------------------------------------------------------------------- + +void MMF::VideoPlayer::play() +{ +#if 0 + TRACE_CONTEXT(VideoPlayer::play, EAudioApi); + TRACE_ENTRY("state %d", m_state); + + switch(m_state) + { + case GroundState: + case LoadingState: + // Is this the correct error? Really we want 'NotReadyError' + m_error = NormalError; + changeState(ErrorState); + break; + + case StoppedState: + case PausedState: + m_player->Play(); + m_tickTimer->start(m_tickInterval); + changeState(PlayingState); + break; + + case PlayingState: + case BufferingState: + case ErrorState: + // Do nothing + break; + + // Protection against adding new states and forgetting to update this switch + default: + TRACE_PANIC(InvalidStatePanic); + } + + TRACE_EXIT("state %d", m_state); +#endif +} + +void MMF::VideoPlayer::pause() +{ +#if 0 + TRACE_CONTEXT(VideoPlayer::pause, EAudioApi); + TRACE_ENTRY("state %d", m_state); + + switch(m_state) + { + case GroundState: + case LoadingState: + case StoppedState: + case PausedState: + case ErrorState: + // Do nothing + break; + + case PlayingState: + case BufferingState: + m_player->Pause(); + m_tickTimer->stop(); + changeState(PausedState); + break; + + // Protection against adding new states and forgetting to update this switch + default: + TRACE_PANIC(InvalidStatePanic); + } + + TRACE_EXIT("state %d", m_state); +#endif +} + +void MMF::VideoPlayer::stop() +{ +#if 0 + TRACE_CONTEXT(VideoPlayer::stop, EAudioApi); + TRACE_ENTRY("state %d", m_state); + + switch(m_state) + { + case GroundState: + case LoadingState: + case StoppedState: + case ErrorState: + // Do nothing + break; + + case PlayingState: + case BufferingState: + case PausedState: + m_player->Stop(); + m_tickTimer->stop(); + changeState(StoppedState); + break; + + // Protection against adding new states and forgetting to update this switch + default: + TRACE_PANIC(InvalidStatePanic); + } + + TRACE_EXIT("state %d", m_state); +#endif +} + +void MMF::VideoPlayer::seek(qint64 ms) +{ +#if 0 + TRACE_CONTEXT(VideoPlayer::seek, EAudioApi); + TRACE_ENTRY("state %d pos %Ld", m_state, ms); + + m_player->SetPosition(TTimeIntervalMicroSeconds(ms)); + + TRACE_EXIT_0(); +#endif +} + +qint32 MMF::VideoPlayer::tickInterval() const +{ +#if 0 + TRACE_CONTEXT(VideoPlayer::tickInterval, EAudioApi); + TRACE_ENTRY("state %d", m_state); + + TRACE_RETURN("%d", m_tickInterval); +#endif +} + +void MMF::VideoPlayer::setTickInterval(qint32 interval) +{ +#if 0 + TRACE_CONTEXT(VideoPlayer::setTickInterval, EAudioApi); + TRACE_ENTRY("state %d m_interval %d interval %d", m_state, m_tickInterval, interval); + + m_tickInterval = interval; + m_tickTimer->setInterval(interval); + + TRACE_EXIT_0(); +#endif +} + +bool MMF::VideoPlayer::hasVideo() const +{ +#if 0 + TRACE_CONTEXT(VideoPlayer::hasVideo, EAudioApi); + TRACE_ENTRY("state %d", m_state); + + // TODO: re-factor this class so that audio playback and video playback are + // delegated to separate classes, which internally hoat a + // CMdaVideoPlayerUtility / CVideoPlayerUtility instance as appropriate. + + TRACE_RETURN("%d", false); +#endif +} + +bool MMF::VideoPlayer::isSeekable() const +{ +#if 0 + TRACE_CONTEXT(VideoPlayer::isSeekable, EAudioApi); + TRACE_ENTRY("state %d", m_state); + + TRACE_RETURN("%d", true); +#endif +} + +Phonon::State MMF::VideoPlayer::state() const +{ +#if 0 + TRACE_CONTEXT(VideoPlayer::state, EAudioApi); + TRACE_ENTRY("state %d", m_state); + + const Phonon::State result = phononState(m_state); + + TRACE_RETURN("%d", result); +#endif +} + +qint64 MMF::VideoPlayer::currentTime() const +{ +#if 0 + TRACE_CONTEXT(VideoPlayer::currentTime, EAudioApi); + TRACE_ENTRY("state %d", m_state); + + TTimeIntervalMicroSeconds us; + const TInt err = m_player->GetPosition(us); + + qint64 result = -1; + + if(KErrNone == err) { + result = toMilliSeconds(us); + } + + TRACE_RETURN("%Ld", result); +#endif +} + +QString MMF::VideoPlayer::errorString() const +{ +#if 0 + TRACE_CONTEXT(VideoPlayer::errorString, EAudioApi); + TRACE_ENTRY("state %d", m_state); + + TRACE_EXIT_0(); + // TODO: put in proper error strings + QString result; + return result; +#endif +} + +Phonon::ErrorType MMF::VideoPlayer::errorType() const +{ +#if 0 + TRACE_CONTEXT(VideoPlayer::errorType, EAudioApi); + TRACE_ENTRY("state %d", m_state); + + const Phonon::ErrorType result = (ErrorState == m_state) + ? m_error : NoError; + + TRACE_RETURN("%d", result); +#endif +} + +qint64 MMF::VideoPlayer::totalTime() const +{ +#if 0 + TRACE_CONTEXT(VideoPlayer::totalTime, EAudioApi); + TRACE_ENTRY("state %d", m_state); + + const qint64 result = toMilliSeconds(m_player->Duration()); + + TRACE_RETURN("%Ld", result); +#endif +} + +MediaSource MMF::VideoPlayer::source() const +{ +#if 0 + TRACE_CONTEXT(VideoPlayer::source, EAudioApi); + TRACE_ENTRY("state %d", m_state); + + TRACE_EXIT_0(); + return m_mediaSource; +#endif +} + +void MMF::VideoPlayer::setSource(const MediaSource &source) +{ +#if 0 + TRACE_CONTEXT(VideoPlayer::setSource, EAudioApi); + TRACE_ENTRY("state %d source.type %d", m_state, source.type()); + + m_player->Close(); + changeState(GroundState); + + // TODO: is it correct to assign even if the media type is not supported in + // the switch statement below? + m_mediaSource = source; + + TInt symbianErr = KErrNone; + + switch(m_mediaSource.type()) + { + case MediaSource::LocalFile: + { + // TODO: work out whose responsibility it is to ensure that paths + // are Symbian-style, i.e. have backslashes for path delimiters. + // Until then, use this utility function... + const QHBufC filename = Utils::symbianFilename(m_mediaSource.fileName()); + TRAP(symbianErr, m_player->OpenFileL(*filename)); + break; + } + + case MediaSource::Url: + { + const QHBufC filename(m_mediaSource.url().toString()); + TRAP(symbianErr, m_player->OpenUrlL(*filename)); + break; + } + + case MediaSource::Invalid: + case MediaSource::Disc: + case MediaSource::Stream: + symbianErr = KErrNotSupported; + break; + + case MediaSource::Empty: + TRACE_EXIT_0(); + return; + + // Protection against adding new media types and forgetting to update this switch + default: + TRACE_PANIC(InvalidMediaTypePanic); + } + + if(KErrNone == symbianErr) + { +#ifdef QT_PHONON_MMF_AUDIO_DRM + // There appears to be a bug in the CDrmPlayerUtility implementation (at least + // in S60 5.x) whereby the player does not check whether the loading observer + // pointer is null before dereferencing it. Therefore we must register for + // loading notification, even though we do nothing in the callback functions. + m_player->RegisterForAudioLoadingNotification(*this); +#endif + changeState(LoadingState); + } + else + { + // TODO: do something with the value of symbianErr? + m_error = NormalError; + changeState(ErrorState); + } + + TRACE_EXIT_0(); +#endif +} + +void MMF::VideoPlayer::setNextSource(const MediaSource &source) +{ +#if 0 + TRACE_CONTEXT(VideoPlayer::setNextSource, EAudioApi); + TRACE_ENTRY("state %d", m_state); + + // TODO: handle 'next source' + + m_nextSource = source; + Q_UNUSED(source); + + TRACE_EXIT_0(); +#endif +} + +qint32 MMF::VideoPlayer::prefinishMark() const +{ +#if 0 + TRACE_CONTEXT(VideoPlayer::prefinishMark, EAudioApi); + TRACE_ENTRY("state %d", m_state); + + // TODO: implement prefinish mark + const qint32 result = 0; + TRACE_RETURN("%d", result); +#endif +} + +void MMF::VideoPlayer::setPrefinishMark(qint32 mark) +{ +#if 0 + TRACE_CONTEXT(VideoPlayer::setPrefinishMark, EAudioApi); + TRACE_ENTRY("state %d mark %d", m_state, mark); + Q_UNUSED(mark); // to silence warnings in release builds + + // TODO: implement prefinish mark + + TRACE_EXIT_0(); +#endif +} + +qint32 MMF::VideoPlayer::transitionTime() const +{ +#if 0 + TRACE_CONTEXT(VideoPlayer::transitionTime, EAudioApi); + TRACE_ENTRY("state %d", m_state); + + // TODO: implement transition time + const qint32 result = 0; + TRACE_RETURN("%d", result); +#endif +} + +void MMF::VideoPlayer::setTransitionTime(qint32 time) +{ +#if 0 + TRACE_CONTEXT(VideoPlayer::setTransitionTime, EAudioApi); + TRACE_ENTRY("state %d time %d", m_state, time); + Q_UNUSED(time); // to silence warnings in release builds + + // TODO: implement transition time + + TRACE_EXIT_0(); +#endif +} + + +//----------------------------------------------------------------------------- +// Volume +//----------------------------------------------------------------------------- + +qreal MMF::VideoPlayer::volume() const +{ + //return m_volume; +} + +bool MMF::VideoPlayer::setVolume(qreal volume) +{ +#if 0 + TRACE_CONTEXT(VideoPlayer::setVolume, EAudioInternal); + TRACE_ENTRY("state %d", m_state); + + bool volumeChanged = false; + + switch(m_state) + { + case GroundState: + case LoadingState: + case ErrorState: + // Do nothing + break; + + case StoppedState: + case PausedState: + case PlayingState: + case BufferingState: + { + if(volume != m_volume) + { + const int err = m_player->SetVolume(volume * m_maxVolume); + if(KErrNone == err) + { + m_volume = volume; + volumeChanged = true; + } + else + { + m_error = NormalError; + changeState(ErrorState); + } + } + break; + } + + // Protection against adding new states and forgetting to update this + // switch + default: + TRACE_PANIC(InvalidStatePanic); + } + + TRACE_RETURN("%d", volumeChanged); +#endif +} + +void MMF::VideoPlayer::setAudioOutput(AudioOutput* audioOutput) +{ + //m_audioOutput = audioOutput; +} + + +//----------------------------------------------------------------------------- +// Private functions +//----------------------------------------------------------------------------- + +qint64 MMF::VideoPlayer::toMilliSeconds(const TTimeIntervalMicroSeconds &in) +{ + //return in.Int64() / 1000; +} + +Phonon::State MMF::VideoPlayer::phononState(PrivateState state) +{ +#if 0 + const Phonon::State phononState = + GroundState == state + ? Phonon::StoppedState + : static_cast(state); + + return phononState; +#endif +} + +void MMF::VideoPlayer::changeState(PrivateState newState) +{ +#if 0 + TRACE_CONTEXT(VideoPlayer::changeState, EAudioInternal); + TRACE_ENTRY("state %d newState %d", m_state, newState); + + // TODO: add some invariants to check that the transition is valid + + const Phonon::State currentPhononState = phononState(m_state); + const Phonon::State newPhononState = phononState(newState); + if(currentPhononState != newPhononState) + { + TRACE("emit stateChanged(%d, %d)", newPhononState, currentPhononState); + emit stateChanged(newPhononState, currentPhononState); + } + + m_state = newState; + + TRACE_EXIT_0(); +#endif +} + +void MMF::VideoPlayer::tick() +{ +#if 0 + TRACE_CONTEXT(VideoPlayer::tick, EAudioInternal); + TRACE_ENTRY("state %d", m_state); + + emit tick(currentTime()); + + TRACE_EXIT_0(); +#endif +} + diff --git a/src/3rdparty/phonon/mmf/mmf_videoplayer.h b/src/3rdparty/phonon/mmf/mmf_videoplayer.h new file mode 100644 index 0000000..3b0cd98 --- /dev/null +++ b/src/3rdparty/phonon/mmf/mmf_videoplayer.h @@ -0,0 +1,163 @@ +/* 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 . + +*/ + +#ifndef PHONON_MMF_VIDEOPLAYER_H +#define PHONON_MMF_VIDEOPLAYER_H + +/* We use the extra qualification include/ to avoid picking up the include + * Phonon has. */ +#include +#include "abstractplayer.h" + +#include + +class CDrmPlayerUtility; +class TTimeIntervalMicroSeconds; +class QTimer; + +namespace Phonon +{ + namespace MMF + { + class AudioOutput; + + /** + * + * See + * How to + * play a video file using CVideoPlayerUtility + */ + class VideoPlayer : public AbstractPlayer + { + Q_OBJECT + public: + VideoPlayer(QObject *parent); + virtual ~VideoPlayer(); + + // AbstractPlayer + virtual void play(); + virtual void pause(); + virtual void stop(); + virtual void seek(qint64 milliseconds); + virtual qint32 tickInterval() const; + virtual void setTickInterval(qint32 interval); + virtual bool hasVideo() const; + virtual bool isSeekable() const; + virtual qint64 currentTime() const; + virtual Phonon::State state() const; + virtual QString errorString() const; + virtual Phonon::ErrorType errorType() const; + virtual qint64 totalTime() const; + virtual MediaSource source() const; + virtual void setSource(const MediaSource &); + virtual void setNextSource(const MediaSource &source); + virtual qint32 prefinishMark() const; + virtual void setPrefinishMark(qint32); + virtual qint32 transitionTime() const; + virtual void setTransitionTime(qint32); + +#ifdef QT_PHONON_MMF_AUDIO_DRM + // MDrmVideoPlayerCallback + virtual void MdapcInitComplete(TInt aError, + const TTimeIntervalMicroSeconds &aDuration); + virtual void MdapcPlayComplete(TInt aError); + + // MAudioLoadingObserver + virtual void MaloLoadingStarted(); + virtual void MaloLoadingComplete(); +#else + // MMdaVideoPlayerCallback + virtual void MapcInitComplete(TInt aError, + const TTimeIntervalMicroSeconds &aDuration); + virtual void MapcPlayComplete(TInt aError); +#endif + + qreal volume() const; + bool setVolume(qreal volume); + + void setAudioOutput(AudioOutput* audioOutput); + + Q_SIGNALS: + void totalTimeChanged(); + void stateChanged(Phonon::State oldState, + Phonon::State newState); + void finished(); + void tick(qint64 time); + + private Q_SLOTS: + /** + * Receives signal from m_tickTimer + */ + void tick(); + + private: + static qint64 toMilliSeconds(const TTimeIntervalMicroSeconds &); + + /** + * Defined private state enumeration in order to add GroundState + */ + enum PrivateState + { + LoadingState = Phonon::LoadingState, + StoppedState = Phonon::StoppedState, + PlayingState = Phonon::PlayingState, + BufferingState = Phonon::BufferingState, + PausedState = Phonon::PausedState, + ErrorState = Phonon::ErrorState, + GroundState + }; + + /** + * Converts PrivateState into the corresponding Phonon::State + */ + static Phonon::State phononState(PrivateState state); + + /** + * Changes state and emits stateChanged() + */ + void changeState(PrivateState newState); + + /** + * Using CPlayerType typedef in order to be able to easily switch between + * CMdaVideoPlayerUtility and CDrmPlayerUtility + */ + // CPlayerType* m_player; TODO + + AudioOutput* m_audioOutput; + + ErrorType m_error; + + /** + * Do not set this directly - call changeState() instead. + */ + PrivateState m_state; + + qint32 m_tickInterval; + + QTimer* m_tickTimer; + + MediaSource m_mediaSource; + MediaSource m_nextSource; + + qreal m_volume; + int m_maxVolume; + }; + } +} + +#endif diff --git a/src/plugins/phonon/mmf/mmf.pro b/src/plugins/phonon/mmf/mmf.pro index ee2d3f9..266c3db 100644 --- a/src/plugins/phonon/mmf/mmf.pro +++ b/src/plugins/phonon/mmf/mmf.pro @@ -21,17 +21,22 @@ phonon_mmf_audio_drm { LIBS += -lmediaclientaudio.lib } -HEADERS += \ - $$PHONON_MMF_DIR/audiooutput.h \ - $$PHONON_MMF_DIR/backend.h \ - $$PHONON_MMF_DIR/mediaobject.h \ - $$PHONON_MMF_DIR/utils.h - -SOURCES += \ - $$PHONON_MMF_DIR/audiooutput.cpp \ - $$PHONON_MMF_DIR/backend.cpp \ - $$PHONON_MMF_DIR/mediaobject.cpp \ - $$PHONON_MMF_DIR/utils.cpp +HEADERS += \ + $$PHONON_MMF_DIR/abstractplayer.h \ + $$PHONON_MMF_DIR/audiooutput.h \ + $$PHONON_MMF_DIR/audioplayer.h \ + $$PHONON_MMF_DIR/backend.h \ + $$PHONON_MMF_DIR/mediaobject.h \ + $$PHONON_MMF_DIR/utils.h \ + $$PHONON_MMF_DIR/mmf_videoplayer.h + +SOURCES += \ + $$PHONON_MMF_DIR/audiooutput.cpp \ + $$PHONON_MMF_DIR/audioplayer.cpp \ + $$PHONON_MMF_DIR/backend.cpp \ + $$PHONON_MMF_DIR/mediaobject.cpp \ + $$PHONON_MMF_DIR/utils.cpp \ + $$PHONON_MMF_DIR/mmf_videoplayer.cpp # This is needed for having the .qtplugin file properly created on Symbian. QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/phonon_backend -- cgit v0.12 From a7b1ad0b2ecdedd5f2a9d52fe09c4497078bc669 Mon Sep 17 00:00:00 2001 From: Frans Englich Date: Mon, 17 Aug 2009 16:58:44 +0200 Subject: Delegate from MediaObject. --- src/3rdparty/phonon/mmf/abstractplayer.h | 13 +++++++++++++ src/3rdparty/phonon/mmf/mediaobject.cpp | 25 ++++++++++++++++++++++++- src/3rdparty/phonon/mmf/mediaobject.h | 4 ++++ 3 files changed, 41 insertions(+), 1 deletion(-) diff --git a/src/3rdparty/phonon/mmf/abstractplayer.h b/src/3rdparty/phonon/mmf/abstractplayer.h index 6452090..0188068 100644 --- a/src/3rdparty/phonon/mmf/abstractplayer.h +++ b/src/3rdparty/phonon/mmf/abstractplayer.h @@ -27,6 +27,8 @@ namespace Phonon { namespace MMF { + class AudioOutput; + class AbstractPlayer : public QObject { public: @@ -42,9 +44,20 @@ namespace Phonon virtual Phonon::State state() const = 0; virtual QString errorString() const = 0; virtual Phonon::ErrorType errorType() const = 0; + virtual qint64 totalTime() const = 0; virtual Phonon::MediaSource source() const = 0; virtual void setSource(const Phonon::MediaSource &) = 0; virtual void setNextSource(const Phonon::MediaSource &) = 0; + + virtual void setTransitionTime(qint32) = 0; + virtual qint32 transitionTime() const = 0; + virtual qint32 prefinishMark() const = 0; + virtual void setPrefinishMark(qint32) = 0; + + virtual bool setVolume(qreal) = 0; + virtual qreal volume() const = 0; + + virtual void setAudioOutput(AudioOutput *) = 0; }; } } diff --git a/src/3rdparty/phonon/mmf/mediaobject.cpp b/src/3rdparty/phonon/mmf/mediaobject.cpp index fb079f0..4769249 100644 --- a/src/3rdparty/phonon/mmf/mediaobject.cpp +++ b/src/3rdparty/phonon/mmf/mediaobject.cpp @@ -16,6 +16,7 @@ along with this library. If not, see . */ +#include "abstractplayer.h" #include "mediaobject.h" using namespace Phonon; @@ -39,83 +40,102 @@ MMF::MediaObject::~MediaObject() void MMF::MediaObject::play() { + m_player->play(); } void MMF::MediaObject::pause() { + m_player->pause(); } void MMF::MediaObject::stop() { + m_player->stop(); } void MMF::MediaObject::seek(qint64 ms) { - Q_UNUSED(ms); + m_player->seek(ms); } qint32 MMF::MediaObject::tickInterval() const { + return m_player->tickInterval(); } void MMF::MediaObject::setTickInterval(qint32 interval) { + m_player->setTransitionTime(interval); } bool MMF::MediaObject::hasVideo() const { + return m_player->hasVideo(); } bool MMF::MediaObject::isSeekable() const { + return m_player->isSeekable(); } Phonon::State MMF::MediaObject::state() const { + return m_player->state(); } qint64 MMF::MediaObject::currentTime() const { + return m_player->currentTime(); } QString MMF::MediaObject::errorString() const { + return m_player->errorString(); } Phonon::ErrorType MMF::MediaObject::errorType() const { + return m_player->errorType(); } qint64 MMF::MediaObject::totalTime() const { + return m_player->totalTime(); } MediaSource MMF::MediaObject::source() const { + return m_player->source(); } void MMF::MediaObject::setSource(const MediaSource &source) { + return m_player->setSource(source); } void MMF::MediaObject::setNextSource(const MediaSource &source) { + return m_player->setNextSource(source); } qint32 MMF::MediaObject::prefinishMark() const { + return m_player->prefinishMark(); } void MMF::MediaObject::setPrefinishMark(qint32 mark) { + m_player->setPrefinishMark(mark); } qint32 MMF::MediaObject::transitionTime() const { + return m_player->transitionTime(); } void MMF::MediaObject::setTransitionTime(qint32 time) { + m_player->setTransitionTime(time); } //----------------------------------------------------------------------------- @@ -124,13 +144,16 @@ void MMF::MediaObject::setTransitionTime(qint32 time) qreal MMF::MediaObject::volume() const { + return m_player->volume(); } bool MMF::MediaObject::setVolume(qreal volume) { + return m_player->setVolume(volume); } void MMF::MediaObject::setAudioOutput(AudioOutput* audioOutput) { + m_player->setAudioOutput(audioOutput); } diff --git a/src/3rdparty/phonon/mmf/mediaobject.h b/src/3rdparty/phonon/mmf/mediaobject.h index d162455..9b1e914 100644 --- a/src/3rdparty/phonon/mmf/mediaobject.h +++ b/src/3rdparty/phonon/mmf/mediaobject.h @@ -26,6 +26,7 @@ namespace Phonon { namespace MMF { + class AbstractPlayer; class AudioOutput; /** @@ -73,6 +74,9 @@ namespace Phonon Phonon::State newState); void finished(); void tick(qint64 time); + + private: + AbstractPlayer *m_player; }; } } -- cgit v0.12 From 427c415d876d57042a55e8b66730888512ac0ed1 Mon Sep 17 00:00:00 2001 From: Gareth Stockwell Date: Mon, 17 Aug 2009 16:02:58 +0100 Subject: Added recognizer code to determine if file is audio or video --- src/3rdparty/phonon/mmf/mediaobject.cpp | 58 +++++++++++++++++++++++++++++++++ src/3rdparty/phonon/mmf/mediaobject.h | 10 ++++++ src/plugins/phonon/mmf/mmf.pro | 3 ++ 3 files changed, 71 insertions(+) diff --git a/src/3rdparty/phonon/mmf/mediaobject.cpp b/src/3rdparty/phonon/mmf/mediaobject.cpp index 8a4b76e..6bf15e6 100644 --- a/src/3rdparty/phonon/mmf/mediaobject.cpp +++ b/src/3rdparty/phonon/mmf/mediaobject.cpp @@ -53,6 +53,10 @@ MMF::MediaObject::MediaObject(QObject *parent) : m_player(NULL) Q_UNUSED(parent); + TInt err = m_recognizer.Connect(); + err = m_fileServer.Connect(); + // TODO: handle this error + // TODO: should leaves be trapped in the constructor? m_player = CPlayerType::NewL(*this, 0, EMdaPriorityPreferenceNone); @@ -70,9 +74,63 @@ MMF::MediaObject::~MediaObject() delete m_tickTimer; delete m_player; + m_fileServer.Close(); + m_recognizer.Close(); + TRACE_EXIT_0(); } + +//----------------------------------------------------------------------------- +// Recognizer +//----------------------------------------------------------------------------- + +const TInt KMimePrefixLength = 6; // either "audio/" or "video/" +_LIT(KMimePrefixAudio, "audio/"); +_LIT(KMimePrefixVideo, "video/"); + +MMF::MediaObject::MediaType MMF::MediaObject::mimeTypeToMediaType(const TDesC& mimeType) +{ + MediaType result = MediaTypeUnknown; + + if(mimeType.Left(KMimePrefixLength).Compare(KMimePrefixAudio) == 0) + { + result = MediaTypeAudio; + } + else if(mimeType.Left(KMimePrefixLength).Compare(KMimePrefixVideo) == 0) + { + result = MediaTypeVideo; + } + + return result; +} + + +MMF::MediaObject::MediaType MMF::MediaObject::fileMediaType + (const QString& fileName) +{ + MediaType result = MediaTypeUnknown; + + QHBufC fileNameSymbian = Utils::symbianFilename(m_mediaSource.fileName()); + RFile file; + TInt err = file.Open(m_fileServer, *fileNameSymbian, EFileRead); + + if(KErrNone == err) + { + TDataRecognitionResult recognizerResult; + err = m_recognizer.RecognizeData(file, recognizerResult); + if(KErrNone == err) + { + const TPtrC mimeType = recognizerResult.iDataType.Des(); + result = mimeTypeToMediaType(mimeType); + } + + file.Close(); + } + return result; +} + + //----------------------------------------------------------------------------- // MediaObjectInterface //----------------------------------------------------------------------------- diff --git a/src/3rdparty/phonon/mmf/mediaobject.h b/src/3rdparty/phonon/mmf/mediaobject.h index f17580e..af9bae2 100644 --- a/src/3rdparty/phonon/mmf/mediaobject.h +++ b/src/3rdparty/phonon/mmf/mediaobject.h @@ -40,6 +40,9 @@ typedef CMdaAudioPlayerUtility CPlayerType; typedef MMdaAudioPlayerCallback MPlayerObserverType; #endif +// For recognizer +#include + namespace Phonon { namespace MMF @@ -149,6 +152,13 @@ namespace Phonon */ void changeState(PrivateState newState); + RApaLsSession m_recognizer; + RFs m_fileServer; + enum MediaType { MediaTypeUnknown, MediaTypeAudio, MediaTypeVideo }; + MediaType mimeTypeToMediaType(const TDesC& mimeType); + MediaType fileMediaType(const QString& fileName); + // TODO: urlMediaType function + /** * Using CPlayerType typedef in order to be able to easily switch between * CMdaAudioPlayerUtility and CDrmPlayerUtility diff --git a/src/plugins/phonon/mmf/mmf.pro b/src/plugins/phonon/mmf/mmf.pro index ee2d3f9..3c8a721 100644 --- a/src/plugins/phonon/mmf/mmf.pro +++ b/src/plugins/phonon/mmf/mmf.pro @@ -33,6 +33,9 @@ SOURCES += \ $$PHONON_MMF_DIR/mediaobject.cpp \ $$PHONON_MMF_DIR/utils.cpp +LIBS += -lefsrv # For file server +LIBS += -lapgrfx.lib # For recognizer + # This is needed for having the .qtplugin file properly created on Symbian. QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/phonon_backend -- cgit v0.12 From 257984d8b8cf31394c4f20070ea045f5ae7fa170 Mon Sep 17 00:00:00 2001 From: Frans Englich Date: Mon, 17 Aug 2009 17:24:34 +0200 Subject: More delegation, basic plumbing. --- src/3rdparty/phonon/mmf/abstractplayer.h | 4 +--- src/3rdparty/phonon/mmf/audioplayer.cpp | 16 ++++++++-------- src/3rdparty/phonon/mmf/audioplayer.h | 2 +- src/3rdparty/phonon/mmf/mediaobject.cpp | 19 ++++++++++++++++++- src/3rdparty/phonon/mmf/mediaobject.h | 6 +++++- src/3rdparty/phonon/mmf/mmf_videoplayer.cpp | 14 +++++++------- src/3rdparty/phonon/mmf/mmf_videoplayer.h | 2 +- 7 files changed, 41 insertions(+), 22 deletions(-) diff --git a/src/3rdparty/phonon/mmf/abstractplayer.h b/src/3rdparty/phonon/mmf/abstractplayer.h index 0188068..613831a 100644 --- a/src/3rdparty/phonon/mmf/abstractplayer.h +++ b/src/3rdparty/phonon/mmf/abstractplayer.h @@ -37,7 +37,7 @@ namespace Phonon virtual void stop() = 0; virtual void seek(qint64 milliseconds) = 0; virtual qint32 tickInterval() const = 0; - virtual void setTickInterval() const = 0; + virtual void setTickInterval(qint32) = 0; virtual bool hasVideo() const = 0; virtual bool isSeekable() const = 0; virtual qint64 currentTime() const = 0; @@ -53,10 +53,8 @@ namespace Phonon virtual qint32 transitionTime() const = 0; virtual qint32 prefinishMark() const = 0; virtual void setPrefinishMark(qint32) = 0; - virtual bool setVolume(qreal) = 0; virtual qreal volume() const = 0; - virtual void setAudioOutput(AudioOutput *) = 0; }; } diff --git a/src/3rdparty/phonon/mmf/audioplayer.cpp b/src/3rdparty/phonon/mmf/audioplayer.cpp index 4dd2eb8..106b71b 100644 --- a/src/3rdparty/phonon/mmf/audioplayer.cpp +++ b/src/3rdparty/phonon/mmf/audioplayer.cpp @@ -39,14 +39,14 @@ const int NullMaxVolume = -1; // Constructor / destructor //----------------------------------------------------------------------------- -MMF::AudioPlayer::AudioPlayer(QObject *parent) : m_player(NULL) - , m_audioOutput(NULL) - , m_error(NoError) - , m_state(GroundState) - , m_tickInterval(DefaultTickInterval) - , m_tickTimer(NULL) - , m_volume(0.0) - , m_maxVolume(NullMaxVolume) +MMF::AudioPlayer::AudioPlayer() : m_player(NULL) + , m_audioOutput(NULL) + , m_error(NoError) + , m_state(GroundState) + , m_tickInterval(DefaultTickInterval) + , m_tickTimer(NULL) + , m_volume(0.0) + , m_maxVolume(NullMaxVolume) { TRACE_CONTEXT(AudioPlayer::AudioPlayer, EAudioApi); TRACE_ENTRY_0(); diff --git a/src/3rdparty/phonon/mmf/audioplayer.h b/src/3rdparty/phonon/mmf/audioplayer.h index d9a64e1..338c6fa 100644 --- a/src/3rdparty/phonon/mmf/audioplayer.h +++ b/src/3rdparty/phonon/mmf/audioplayer.h @@ -56,7 +56,7 @@ namespace Phonon Q_OBJECT public: - AudioPlayer(QObject *parent); + AudioPlayer(); virtual ~AudioPlayer(); // AbstractPlayer diff --git a/src/3rdparty/phonon/mmf/mediaobject.cpp b/src/3rdparty/phonon/mmf/mediaobject.cpp index 4769249..e9e4b5b 100644 --- a/src/3rdparty/phonon/mmf/mediaobject.cpp +++ b/src/3rdparty/phonon/mmf/mediaobject.cpp @@ -17,6 +17,8 @@ along with this library. If not, see . */ #include "abstractplayer.h" +#include "audioplayer.h" +#include "mmf_videoplayer.h" #include "mediaobject.h" using namespace Phonon; @@ -65,7 +67,7 @@ qint32 MMF::MediaObject::tickInterval() const void MMF::MediaObject::setTickInterval(qint32 interval) { - m_player->setTransitionTime(interval); + m_player->setTickInterval(interval); } bool MMF::MediaObject::hasVideo() const @@ -110,9 +112,24 @@ MediaSource MMF::MediaObject::source() const void MMF::MediaObject::setSource(const MediaSource &source) { + loadPlayer(source); + return m_player->setSource(source); } +void MMF::MediaObject::loadPlayer(const MediaSource &source) +{ + disconnect(m_player.data(), 0, this, 0); + + // TODO determine media type + m_player.reset(new AudioPlayer()); + + connect(m_player.data(), SIGNAL(totalTimeChanged()), SIGNAL(totalTimeChanged())); + 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))); +} + void MMF::MediaObject::setNextSource(const MediaSource &source) { return m_player->setNextSource(source); diff --git a/src/3rdparty/phonon/mmf/mediaobject.h b/src/3rdparty/phonon/mmf/mediaobject.h index 9b1e914..a55b6e6 100644 --- a/src/3rdparty/phonon/mmf/mediaobject.h +++ b/src/3rdparty/phonon/mmf/mediaobject.h @@ -21,6 +21,7 @@ along with this library. If not, see . #include #include +#include namespace Phonon { @@ -76,7 +77,10 @@ namespace Phonon void tick(qint64 time); private: - AbstractPlayer *m_player; + void loadPlayer(const MediaSource &source); + + QScopedPointer m_player; + }; } } diff --git a/src/3rdparty/phonon/mmf/mmf_videoplayer.cpp b/src/3rdparty/phonon/mmf/mmf_videoplayer.cpp index 3a51070..c226835 100644 --- a/src/3rdparty/phonon/mmf/mmf_videoplayer.cpp +++ b/src/3rdparty/phonon/mmf/mmf_videoplayer.cpp @@ -39,13 +39,13 @@ const int NullMaxVolume = -1; // Constructor / destructor //----------------------------------------------------------------------------- -MMF::VideoPlayer::VideoPlayer(QObject *parent) : m_audioOutput(NULL) - , m_error(NoError) - , m_state(GroundState) - , m_tickInterval(DefaultTickInterval) - , m_tickTimer(NULL) - , m_volume(0.0) - , m_maxVolume(NullMaxVolume) +MMF::VideoPlayer::VideoPlayer() : m_audioOutput(NULL) + , m_error(NoError) + , m_state(GroundState) + , m_tickInterval(DefaultTickInterval) + , m_tickTimer(NULL) + , m_volume(0.0) + , m_maxVolume(NullMaxVolume) { #if 0 TRACE_CONTEXT(VideoPlayer::VideoPlayer, EAudioApi); diff --git a/src/3rdparty/phonon/mmf/mmf_videoplayer.h b/src/3rdparty/phonon/mmf/mmf_videoplayer.h index 3b0cd98..3ea9c1a 100644 --- a/src/3rdparty/phonon/mmf/mmf_videoplayer.h +++ b/src/3rdparty/phonon/mmf/mmf_videoplayer.h @@ -46,7 +46,7 @@ namespace Phonon { Q_OBJECT public: - VideoPlayer(QObject *parent); + VideoPlayer(); virtual ~VideoPlayer(); // AbstractPlayer -- cgit v0.12 From 6b7603a0a2fed844b1264d8deb0ce78b110858c4 Mon Sep 17 00:00:00 2001 From: Frans Englich Date: Mon, 17 Aug 2009 17:31:02 +0200 Subject: Rename mmf_videoplayer back to videoplayer, apparently the includes can be resolved anyway. --- src/3rdparty/phonon/mmf/mediaobject.cpp | 2 +- src/3rdparty/phonon/mmf/mmf_videoplayer.cpp | 577 ---------------------------- src/3rdparty/phonon/mmf/mmf_videoplayer.h | 163 -------- src/3rdparty/phonon/mmf/videoplayer.cpp | 577 ++++++++++++++++++++++++++++ src/3rdparty/phonon/mmf/videoplayer.h | 163 ++++++++ src/plugins/phonon/mmf/mmf.pro | 4 +- 6 files changed, 743 insertions(+), 743 deletions(-) delete mode 100644 src/3rdparty/phonon/mmf/mmf_videoplayer.cpp delete mode 100644 src/3rdparty/phonon/mmf/mmf_videoplayer.h create mode 100644 src/3rdparty/phonon/mmf/videoplayer.cpp create mode 100644 src/3rdparty/phonon/mmf/videoplayer.h diff --git a/src/3rdparty/phonon/mmf/mediaobject.cpp b/src/3rdparty/phonon/mmf/mediaobject.cpp index e9e4b5b..877e463 100644 --- a/src/3rdparty/phonon/mmf/mediaobject.cpp +++ b/src/3rdparty/phonon/mmf/mediaobject.cpp @@ -18,7 +18,7 @@ along with this library. If not, see . #include "abstractplayer.h" #include "audioplayer.h" -#include "mmf_videoplayer.h" +#include "videoplayer.h" #include "mediaobject.h" using namespace Phonon; diff --git a/src/3rdparty/phonon/mmf/mmf_videoplayer.cpp b/src/3rdparty/phonon/mmf/mmf_videoplayer.cpp deleted file mode 100644 index c226835..0000000 --- a/src/3rdparty/phonon/mmf/mmf_videoplayer.cpp +++ /dev/null @@ -1,577 +0,0 @@ -/* 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 . - -*/ - -#include -#include -#include - -#include "mmf_videoplayer.h" -#include "audiooutput.h" -#include "utils.h" - -using namespace Phonon; -using namespace Phonon::MMF; - -//----------------------------------------------------------------------------- -// Constants -//----------------------------------------------------------------------------- - -const qint32 DefaultTickInterval = 20; -const int NullMaxVolume = -1; - - -//----------------------------------------------------------------------------- -// Constructor / destructor -//----------------------------------------------------------------------------- - -MMF::VideoPlayer::VideoPlayer() : m_audioOutput(NULL) - , m_error(NoError) - , m_state(GroundState) - , m_tickInterval(DefaultTickInterval) - , m_tickTimer(NULL) - , m_volume(0.0) - , m_maxVolume(NullMaxVolume) -{ -#if 0 - TRACE_CONTEXT(VideoPlayer::VideoPlayer, EAudioApi); - TRACE_ENTRY_0(); - - Q_UNUSED(parent); - - // TODO: should leaves be trapped in the constructor? - m_player = CPlayerType::NewL(*this, 0, EMdaPriorityPreferenceNone); - - m_tickTimer = new QTimer(this); - connect(m_tickTimer, SIGNAL(timeout()), this, SLOT(tick())); - - TRACE_EXIT_0(); -#endif -} - -MMF::VideoPlayer::~VideoPlayer() -{ -#if 0 - TRACE_CONTEXT(VideoPlayer::~VideoPlayer, EAudioApi); - TRACE_ENTRY_0(); - - delete m_tickTimer; - delete m_player; - - TRACE_EXIT_0(); -#endif -} - -//----------------------------------------------------------------------------- -// VideoPlayerInterface -//----------------------------------------------------------------------------- - -void MMF::VideoPlayer::play() -{ -#if 0 - TRACE_CONTEXT(VideoPlayer::play, EAudioApi); - TRACE_ENTRY("state %d", m_state); - - switch(m_state) - { - case GroundState: - case LoadingState: - // Is this the correct error? Really we want 'NotReadyError' - m_error = NormalError; - changeState(ErrorState); - break; - - case StoppedState: - case PausedState: - m_player->Play(); - m_tickTimer->start(m_tickInterval); - changeState(PlayingState); - break; - - case PlayingState: - case BufferingState: - case ErrorState: - // Do nothing - break; - - // Protection against adding new states and forgetting to update this switch - default: - TRACE_PANIC(InvalidStatePanic); - } - - TRACE_EXIT("state %d", m_state); -#endif -} - -void MMF::VideoPlayer::pause() -{ -#if 0 - TRACE_CONTEXT(VideoPlayer::pause, EAudioApi); - TRACE_ENTRY("state %d", m_state); - - switch(m_state) - { - case GroundState: - case LoadingState: - case StoppedState: - case PausedState: - case ErrorState: - // Do nothing - break; - - case PlayingState: - case BufferingState: - m_player->Pause(); - m_tickTimer->stop(); - changeState(PausedState); - break; - - // Protection against adding new states and forgetting to update this switch - default: - TRACE_PANIC(InvalidStatePanic); - } - - TRACE_EXIT("state %d", m_state); -#endif -} - -void MMF::VideoPlayer::stop() -{ -#if 0 - TRACE_CONTEXT(VideoPlayer::stop, EAudioApi); - TRACE_ENTRY("state %d", m_state); - - switch(m_state) - { - case GroundState: - case LoadingState: - case StoppedState: - case ErrorState: - // Do nothing - break; - - case PlayingState: - case BufferingState: - case PausedState: - m_player->Stop(); - m_tickTimer->stop(); - changeState(StoppedState); - break; - - // Protection against adding new states and forgetting to update this switch - default: - TRACE_PANIC(InvalidStatePanic); - } - - TRACE_EXIT("state %d", m_state); -#endif -} - -void MMF::VideoPlayer::seek(qint64 ms) -{ -#if 0 - TRACE_CONTEXT(VideoPlayer::seek, EAudioApi); - TRACE_ENTRY("state %d pos %Ld", m_state, ms); - - m_player->SetPosition(TTimeIntervalMicroSeconds(ms)); - - TRACE_EXIT_0(); -#endif -} - -qint32 MMF::VideoPlayer::tickInterval() const -{ -#if 0 - TRACE_CONTEXT(VideoPlayer::tickInterval, EAudioApi); - TRACE_ENTRY("state %d", m_state); - - TRACE_RETURN("%d", m_tickInterval); -#endif -} - -void MMF::VideoPlayer::setTickInterval(qint32 interval) -{ -#if 0 - TRACE_CONTEXT(VideoPlayer::setTickInterval, EAudioApi); - TRACE_ENTRY("state %d m_interval %d interval %d", m_state, m_tickInterval, interval); - - m_tickInterval = interval; - m_tickTimer->setInterval(interval); - - TRACE_EXIT_0(); -#endif -} - -bool MMF::VideoPlayer::hasVideo() const -{ -#if 0 - TRACE_CONTEXT(VideoPlayer::hasVideo, EAudioApi); - TRACE_ENTRY("state %d", m_state); - - // TODO: re-factor this class so that audio playback and video playback are - // delegated to separate classes, which internally hoat a - // CMdaVideoPlayerUtility / CVideoPlayerUtility instance as appropriate. - - TRACE_RETURN("%d", false); -#endif -} - -bool MMF::VideoPlayer::isSeekable() const -{ -#if 0 - TRACE_CONTEXT(VideoPlayer::isSeekable, EAudioApi); - TRACE_ENTRY("state %d", m_state); - - TRACE_RETURN("%d", true); -#endif -} - -Phonon::State MMF::VideoPlayer::state() const -{ -#if 0 - TRACE_CONTEXT(VideoPlayer::state, EAudioApi); - TRACE_ENTRY("state %d", m_state); - - const Phonon::State result = phononState(m_state); - - TRACE_RETURN("%d", result); -#endif -} - -qint64 MMF::VideoPlayer::currentTime() const -{ -#if 0 - TRACE_CONTEXT(VideoPlayer::currentTime, EAudioApi); - TRACE_ENTRY("state %d", m_state); - - TTimeIntervalMicroSeconds us; - const TInt err = m_player->GetPosition(us); - - qint64 result = -1; - - if(KErrNone == err) { - result = toMilliSeconds(us); - } - - TRACE_RETURN("%Ld", result); -#endif -} - -QString MMF::VideoPlayer::errorString() const -{ -#if 0 - TRACE_CONTEXT(VideoPlayer::errorString, EAudioApi); - TRACE_ENTRY("state %d", m_state); - - TRACE_EXIT_0(); - // TODO: put in proper error strings - QString result; - return result; -#endif -} - -Phonon::ErrorType MMF::VideoPlayer::errorType() const -{ -#if 0 - TRACE_CONTEXT(VideoPlayer::errorType, EAudioApi); - TRACE_ENTRY("state %d", m_state); - - const Phonon::ErrorType result = (ErrorState == m_state) - ? m_error : NoError; - - TRACE_RETURN("%d", result); -#endif -} - -qint64 MMF::VideoPlayer::totalTime() const -{ -#if 0 - TRACE_CONTEXT(VideoPlayer::totalTime, EAudioApi); - TRACE_ENTRY("state %d", m_state); - - const qint64 result = toMilliSeconds(m_player->Duration()); - - TRACE_RETURN("%Ld", result); -#endif -} - -MediaSource MMF::VideoPlayer::source() const -{ -#if 0 - TRACE_CONTEXT(VideoPlayer::source, EAudioApi); - TRACE_ENTRY("state %d", m_state); - - TRACE_EXIT_0(); - return m_mediaSource; -#endif -} - -void MMF::VideoPlayer::setSource(const MediaSource &source) -{ -#if 0 - TRACE_CONTEXT(VideoPlayer::setSource, EAudioApi); - TRACE_ENTRY("state %d source.type %d", m_state, source.type()); - - m_player->Close(); - changeState(GroundState); - - // TODO: is it correct to assign even if the media type is not supported in - // the switch statement below? - m_mediaSource = source; - - TInt symbianErr = KErrNone; - - switch(m_mediaSource.type()) - { - case MediaSource::LocalFile: - { - // TODO: work out whose responsibility it is to ensure that paths - // are Symbian-style, i.e. have backslashes for path delimiters. - // Until then, use this utility function... - const QHBufC filename = Utils::symbianFilename(m_mediaSource.fileName()); - TRAP(symbianErr, m_player->OpenFileL(*filename)); - break; - } - - case MediaSource::Url: - { - const QHBufC filename(m_mediaSource.url().toString()); - TRAP(symbianErr, m_player->OpenUrlL(*filename)); - break; - } - - case MediaSource::Invalid: - case MediaSource::Disc: - case MediaSource::Stream: - symbianErr = KErrNotSupported; - break; - - case MediaSource::Empty: - TRACE_EXIT_0(); - return; - - // Protection against adding new media types and forgetting to update this switch - default: - TRACE_PANIC(InvalidMediaTypePanic); - } - - if(KErrNone == symbianErr) - { -#ifdef QT_PHONON_MMF_AUDIO_DRM - // There appears to be a bug in the CDrmPlayerUtility implementation (at least - // in S60 5.x) whereby the player does not check whether the loading observer - // pointer is null before dereferencing it. Therefore we must register for - // loading notification, even though we do nothing in the callback functions. - m_player->RegisterForAudioLoadingNotification(*this); -#endif - changeState(LoadingState); - } - else - { - // TODO: do something with the value of symbianErr? - m_error = NormalError; - changeState(ErrorState); - } - - TRACE_EXIT_0(); -#endif -} - -void MMF::VideoPlayer::setNextSource(const MediaSource &source) -{ -#if 0 - TRACE_CONTEXT(VideoPlayer::setNextSource, EAudioApi); - TRACE_ENTRY("state %d", m_state); - - // TODO: handle 'next source' - - m_nextSource = source; - Q_UNUSED(source); - - TRACE_EXIT_0(); -#endif -} - -qint32 MMF::VideoPlayer::prefinishMark() const -{ -#if 0 - TRACE_CONTEXT(VideoPlayer::prefinishMark, EAudioApi); - TRACE_ENTRY("state %d", m_state); - - // TODO: implement prefinish mark - const qint32 result = 0; - TRACE_RETURN("%d", result); -#endif -} - -void MMF::VideoPlayer::setPrefinishMark(qint32 mark) -{ -#if 0 - TRACE_CONTEXT(VideoPlayer::setPrefinishMark, EAudioApi); - TRACE_ENTRY("state %d mark %d", m_state, mark); - Q_UNUSED(mark); // to silence warnings in release builds - - // TODO: implement prefinish mark - - TRACE_EXIT_0(); -#endif -} - -qint32 MMF::VideoPlayer::transitionTime() const -{ -#if 0 - TRACE_CONTEXT(VideoPlayer::transitionTime, EAudioApi); - TRACE_ENTRY("state %d", m_state); - - // TODO: implement transition time - const qint32 result = 0; - TRACE_RETURN("%d", result); -#endif -} - -void MMF::VideoPlayer::setTransitionTime(qint32 time) -{ -#if 0 - TRACE_CONTEXT(VideoPlayer::setTransitionTime, EAudioApi); - TRACE_ENTRY("state %d time %d", m_state, time); - Q_UNUSED(time); // to silence warnings in release builds - - // TODO: implement transition time - - TRACE_EXIT_0(); -#endif -} - - -//----------------------------------------------------------------------------- -// Volume -//----------------------------------------------------------------------------- - -qreal MMF::VideoPlayer::volume() const -{ - //return m_volume; -} - -bool MMF::VideoPlayer::setVolume(qreal volume) -{ -#if 0 - TRACE_CONTEXT(VideoPlayer::setVolume, EAudioInternal); - TRACE_ENTRY("state %d", m_state); - - bool volumeChanged = false; - - switch(m_state) - { - case GroundState: - case LoadingState: - case ErrorState: - // Do nothing - break; - - case StoppedState: - case PausedState: - case PlayingState: - case BufferingState: - { - if(volume != m_volume) - { - const int err = m_player->SetVolume(volume * m_maxVolume); - if(KErrNone == err) - { - m_volume = volume; - volumeChanged = true; - } - else - { - m_error = NormalError; - changeState(ErrorState); - } - } - break; - } - - // Protection against adding new states and forgetting to update this - // switch - default: - TRACE_PANIC(InvalidStatePanic); - } - - TRACE_RETURN("%d", volumeChanged); -#endif -} - -void MMF::VideoPlayer::setAudioOutput(AudioOutput* audioOutput) -{ - //m_audioOutput = audioOutput; -} - - -//----------------------------------------------------------------------------- -// Private functions -//----------------------------------------------------------------------------- - -qint64 MMF::VideoPlayer::toMilliSeconds(const TTimeIntervalMicroSeconds &in) -{ - //return in.Int64() / 1000; -} - -Phonon::State MMF::VideoPlayer::phononState(PrivateState state) -{ -#if 0 - const Phonon::State phononState = - GroundState == state - ? Phonon::StoppedState - : static_cast(state); - - return phononState; -#endif -} - -void MMF::VideoPlayer::changeState(PrivateState newState) -{ -#if 0 - TRACE_CONTEXT(VideoPlayer::changeState, EAudioInternal); - TRACE_ENTRY("state %d newState %d", m_state, newState); - - // TODO: add some invariants to check that the transition is valid - - const Phonon::State currentPhononState = phononState(m_state); - const Phonon::State newPhononState = phononState(newState); - if(currentPhononState != newPhononState) - { - TRACE("emit stateChanged(%d, %d)", newPhononState, currentPhononState); - emit stateChanged(newPhononState, currentPhononState); - } - - m_state = newState; - - TRACE_EXIT_0(); -#endif -} - -void MMF::VideoPlayer::tick() -{ -#if 0 - TRACE_CONTEXT(VideoPlayer::tick, EAudioInternal); - TRACE_ENTRY("state %d", m_state); - - emit tick(currentTime()); - - TRACE_EXIT_0(); -#endif -} - diff --git a/src/3rdparty/phonon/mmf/mmf_videoplayer.h b/src/3rdparty/phonon/mmf/mmf_videoplayer.h deleted file mode 100644 index 3ea9c1a..0000000 --- a/src/3rdparty/phonon/mmf/mmf_videoplayer.h +++ /dev/null @@ -1,163 +0,0 @@ -/* 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 . - -*/ - -#ifndef PHONON_MMF_VIDEOPLAYER_H -#define PHONON_MMF_VIDEOPLAYER_H - -/* We use the extra qualification include/ to avoid picking up the include - * Phonon has. */ -#include -#include "abstractplayer.h" - -#include - -class CDrmPlayerUtility; -class TTimeIntervalMicroSeconds; -class QTimer; - -namespace Phonon -{ - namespace MMF - { - class AudioOutput; - - /** - * - * See - * How to - * play a video file using CVideoPlayerUtility - */ - class VideoPlayer : public AbstractPlayer - { - Q_OBJECT - public: - VideoPlayer(); - virtual ~VideoPlayer(); - - // AbstractPlayer - virtual void play(); - virtual void pause(); - virtual void stop(); - virtual void seek(qint64 milliseconds); - virtual qint32 tickInterval() const; - virtual void setTickInterval(qint32 interval); - virtual bool hasVideo() const; - virtual bool isSeekable() const; - virtual qint64 currentTime() const; - virtual Phonon::State state() const; - virtual QString errorString() const; - virtual Phonon::ErrorType errorType() const; - virtual qint64 totalTime() const; - virtual MediaSource source() const; - virtual void setSource(const MediaSource &); - virtual void setNextSource(const MediaSource &source); - virtual qint32 prefinishMark() const; - virtual void setPrefinishMark(qint32); - virtual qint32 transitionTime() const; - virtual void setTransitionTime(qint32); - -#ifdef QT_PHONON_MMF_AUDIO_DRM - // MDrmVideoPlayerCallback - virtual void MdapcInitComplete(TInt aError, - const TTimeIntervalMicroSeconds &aDuration); - virtual void MdapcPlayComplete(TInt aError); - - // MAudioLoadingObserver - virtual void MaloLoadingStarted(); - virtual void MaloLoadingComplete(); -#else - // MMdaVideoPlayerCallback - virtual void MapcInitComplete(TInt aError, - const TTimeIntervalMicroSeconds &aDuration); - virtual void MapcPlayComplete(TInt aError); -#endif - - qreal volume() const; - bool setVolume(qreal volume); - - void setAudioOutput(AudioOutput* audioOutput); - - Q_SIGNALS: - void totalTimeChanged(); - void stateChanged(Phonon::State oldState, - Phonon::State newState); - void finished(); - void tick(qint64 time); - - private Q_SLOTS: - /** - * Receives signal from m_tickTimer - */ - void tick(); - - private: - static qint64 toMilliSeconds(const TTimeIntervalMicroSeconds &); - - /** - * Defined private state enumeration in order to add GroundState - */ - enum PrivateState - { - LoadingState = Phonon::LoadingState, - StoppedState = Phonon::StoppedState, - PlayingState = Phonon::PlayingState, - BufferingState = Phonon::BufferingState, - PausedState = Phonon::PausedState, - ErrorState = Phonon::ErrorState, - GroundState - }; - - /** - * Converts PrivateState into the corresponding Phonon::State - */ - static Phonon::State phononState(PrivateState state); - - /** - * Changes state and emits stateChanged() - */ - void changeState(PrivateState newState); - - /** - * Using CPlayerType typedef in order to be able to easily switch between - * CMdaVideoPlayerUtility and CDrmPlayerUtility - */ - // CPlayerType* m_player; TODO - - AudioOutput* m_audioOutput; - - ErrorType m_error; - - /** - * Do not set this directly - call changeState() instead. - */ - PrivateState m_state; - - qint32 m_tickInterval; - - QTimer* m_tickTimer; - - MediaSource m_mediaSource; - MediaSource m_nextSource; - - qreal m_volume; - int m_maxVolume; - }; - } -} - -#endif diff --git a/src/3rdparty/phonon/mmf/videoplayer.cpp b/src/3rdparty/phonon/mmf/videoplayer.cpp new file mode 100644 index 0000000..f465c96 --- /dev/null +++ b/src/3rdparty/phonon/mmf/videoplayer.cpp @@ -0,0 +1,577 @@ +/* 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 . + +*/ + +#include +#include +#include + +#include "videoplayer.h" +#include "audiooutput.h" +#include "utils.h" + +using namespace Phonon; +using namespace Phonon::MMF; + +//----------------------------------------------------------------------------- +// Constants +//----------------------------------------------------------------------------- + +const qint32 DefaultTickInterval = 20; +const int NullMaxVolume = -1; + + +//----------------------------------------------------------------------------- +// Constructor / destructor +//----------------------------------------------------------------------------- + +MMF::VideoPlayer::VideoPlayer() : m_audioOutput(NULL) + , m_error(NoError) + , m_state(GroundState) + , m_tickInterval(DefaultTickInterval) + , m_tickTimer(NULL) + , m_volume(0.0) + , m_maxVolume(NullMaxVolume) +{ +#if 0 + TRACE_CONTEXT(VideoPlayer::VideoPlayer, EAudioApi); + TRACE_ENTRY_0(); + + Q_UNUSED(parent); + + // TODO: should leaves be trapped in the constructor? + m_player = CPlayerType::NewL(*this, 0, EMdaPriorityPreferenceNone); + + m_tickTimer = new QTimer(this); + connect(m_tickTimer, SIGNAL(timeout()), this, SLOT(tick())); + + TRACE_EXIT_0(); +#endif +} + +MMF::VideoPlayer::~VideoPlayer() +{ +#if 0 + TRACE_CONTEXT(VideoPlayer::~VideoPlayer, EAudioApi); + TRACE_ENTRY_0(); + + delete m_tickTimer; + delete m_player; + + TRACE_EXIT_0(); +#endif +} + +//----------------------------------------------------------------------------- +// VideoPlayerInterface +//----------------------------------------------------------------------------- + +void MMF::VideoPlayer::play() +{ +#if 0 + TRACE_CONTEXT(VideoPlayer::play, EAudioApi); + TRACE_ENTRY("state %d", m_state); + + switch(m_state) + { + case GroundState: + case LoadingState: + // Is this the correct error? Really we want 'NotReadyError' + m_error = NormalError; + changeState(ErrorState); + break; + + case StoppedState: + case PausedState: + m_player->Play(); + m_tickTimer->start(m_tickInterval); + changeState(PlayingState); + break; + + case PlayingState: + case BufferingState: + case ErrorState: + // Do nothing + break; + + // Protection against adding new states and forgetting to update this switch + default: + TRACE_PANIC(InvalidStatePanic); + } + + TRACE_EXIT("state %d", m_state); +#endif +} + +void MMF::VideoPlayer::pause() +{ +#if 0 + TRACE_CONTEXT(VideoPlayer::pause, EAudioApi); + TRACE_ENTRY("state %d", m_state); + + switch(m_state) + { + case GroundState: + case LoadingState: + case StoppedState: + case PausedState: + case ErrorState: + // Do nothing + break; + + case PlayingState: + case BufferingState: + m_player->Pause(); + m_tickTimer->stop(); + changeState(PausedState); + break; + + // Protection against adding new states and forgetting to update this switch + default: + TRACE_PANIC(InvalidStatePanic); + } + + TRACE_EXIT("state %d", m_state); +#endif +} + +void MMF::VideoPlayer::stop() +{ +#if 0 + TRACE_CONTEXT(VideoPlayer::stop, EAudioApi); + TRACE_ENTRY("state %d", m_state); + + switch(m_state) + { + case GroundState: + case LoadingState: + case StoppedState: + case ErrorState: + // Do nothing + break; + + case PlayingState: + case BufferingState: + case PausedState: + m_player->Stop(); + m_tickTimer->stop(); + changeState(StoppedState); + break; + + // Protection against adding new states and forgetting to update this switch + default: + TRACE_PANIC(InvalidStatePanic); + } + + TRACE_EXIT("state %d", m_state); +#endif +} + +void MMF::VideoPlayer::seek(qint64 ms) +{ +#if 0 + TRACE_CONTEXT(VideoPlayer::seek, EAudioApi); + TRACE_ENTRY("state %d pos %Ld", m_state, ms); + + m_player->SetPosition(TTimeIntervalMicroSeconds(ms)); + + TRACE_EXIT_0(); +#endif +} + +qint32 MMF::VideoPlayer::tickInterval() const +{ +#if 0 + TRACE_CONTEXT(VideoPlayer::tickInterval, EAudioApi); + TRACE_ENTRY("state %d", m_state); + + TRACE_RETURN("%d", m_tickInterval); +#endif +} + +void MMF::VideoPlayer::setTickInterval(qint32 interval) +{ +#if 0 + TRACE_CONTEXT(VideoPlayer::setTickInterval, EAudioApi); + TRACE_ENTRY("state %d m_interval %d interval %d", m_state, m_tickInterval, interval); + + m_tickInterval = interval; + m_tickTimer->setInterval(interval); + + TRACE_EXIT_0(); +#endif +} + +bool MMF::VideoPlayer::hasVideo() const +{ +#if 0 + TRACE_CONTEXT(VideoPlayer::hasVideo, EAudioApi); + TRACE_ENTRY("state %d", m_state); + + // TODO: re-factor this class so that audio playback and video playback are + // delegated to separate classes, which internally hoat a + // CMdaVideoPlayerUtility / CVideoPlayerUtility instance as appropriate. + + TRACE_RETURN("%d", false); +#endif +} + +bool MMF::VideoPlayer::isSeekable() const +{ +#if 0 + TRACE_CONTEXT(VideoPlayer::isSeekable, EAudioApi); + TRACE_ENTRY("state %d", m_state); + + TRACE_RETURN("%d", true); +#endif +} + +Phonon::State MMF::VideoPlayer::state() const +{ +#if 0 + TRACE_CONTEXT(VideoPlayer::state, EAudioApi); + TRACE_ENTRY("state %d", m_state); + + const Phonon::State result = phononState(m_state); + + TRACE_RETURN("%d", result); +#endif +} + +qint64 MMF::VideoPlayer::currentTime() const +{ +#if 0 + TRACE_CONTEXT(VideoPlayer::currentTime, EAudioApi); + TRACE_ENTRY("state %d", m_state); + + TTimeIntervalMicroSeconds us; + const TInt err = m_player->GetPosition(us); + + qint64 result = -1; + + if(KErrNone == err) { + result = toMilliSeconds(us); + } + + TRACE_RETURN("%Ld", result); +#endif +} + +QString MMF::VideoPlayer::errorString() const +{ +#if 0 + TRACE_CONTEXT(VideoPlayer::errorString, EAudioApi); + TRACE_ENTRY("state %d", m_state); + + TRACE_EXIT_0(); + // TODO: put in proper error strings + QString result; + return result; +#endif +} + +Phonon::ErrorType MMF::VideoPlayer::errorType() const +{ +#if 0 + TRACE_CONTEXT(VideoPlayer::errorType, EAudioApi); + TRACE_ENTRY("state %d", m_state); + + const Phonon::ErrorType result = (ErrorState == m_state) + ? m_error : NoError; + + TRACE_RETURN("%d", result); +#endif +} + +qint64 MMF::VideoPlayer::totalTime() const +{ +#if 0 + TRACE_CONTEXT(VideoPlayer::totalTime, EAudioApi); + TRACE_ENTRY("state %d", m_state); + + const qint64 result = toMilliSeconds(m_player->Duration()); + + TRACE_RETURN("%Ld", result); +#endif +} + +MediaSource MMF::VideoPlayer::source() const +{ +#if 0 + TRACE_CONTEXT(VideoPlayer::source, EAudioApi); + TRACE_ENTRY("state %d", m_state); + + TRACE_EXIT_0(); + return m_mediaSource; +#endif +} + +void MMF::VideoPlayer::setSource(const MediaSource &source) +{ +#if 0 + TRACE_CONTEXT(VideoPlayer::setSource, EAudioApi); + TRACE_ENTRY("state %d source.type %d", m_state, source.type()); + + m_player->Close(); + changeState(GroundState); + + // TODO: is it correct to assign even if the media type is not supported in + // the switch statement below? + m_mediaSource = source; + + TInt symbianErr = KErrNone; + + switch(m_mediaSource.type()) + { + case MediaSource::LocalFile: + { + // TODO: work out whose responsibility it is to ensure that paths + // are Symbian-style, i.e. have backslashes for path delimiters. + // Until then, use this utility function... + const QHBufC filename = Utils::symbianFilename(m_mediaSource.fileName()); + TRAP(symbianErr, m_player->OpenFileL(*filename)); + break; + } + + case MediaSource::Url: + { + const QHBufC filename(m_mediaSource.url().toString()); + TRAP(symbianErr, m_player->OpenUrlL(*filename)); + break; + } + + case MediaSource::Invalid: + case MediaSource::Disc: + case MediaSource::Stream: + symbianErr = KErrNotSupported; + break; + + case MediaSource::Empty: + TRACE_EXIT_0(); + return; + + // Protection against adding new media types and forgetting to update this switch + default: + TRACE_PANIC(InvalidMediaTypePanic); + } + + if(KErrNone == symbianErr) + { +#ifdef QT_PHONON_MMF_AUDIO_DRM + // There appears to be a bug in the CDrmPlayerUtility implementation (at least + // in S60 5.x) whereby the player does not check whether the loading observer + // pointer is null before dereferencing it. Therefore we must register for + // loading notification, even though we do nothing in the callback functions. + m_player->RegisterForAudioLoadingNotification(*this); +#endif + changeState(LoadingState); + } + else + { + // TODO: do something with the value of symbianErr? + m_error = NormalError; + changeState(ErrorState); + } + + TRACE_EXIT_0(); +#endif +} + +void MMF::VideoPlayer::setNextSource(const MediaSource &source) +{ +#if 0 + TRACE_CONTEXT(VideoPlayer::setNextSource, EAudioApi); + TRACE_ENTRY("state %d", m_state); + + // TODO: handle 'next source' + + m_nextSource = source; + Q_UNUSED(source); + + TRACE_EXIT_0(); +#endif +} + +qint32 MMF::VideoPlayer::prefinishMark() const +{ +#if 0 + TRACE_CONTEXT(VideoPlayer::prefinishMark, EAudioApi); + TRACE_ENTRY("state %d", m_state); + + // TODO: implement prefinish mark + const qint32 result = 0; + TRACE_RETURN("%d", result); +#endif +} + +void MMF::VideoPlayer::setPrefinishMark(qint32 mark) +{ +#if 0 + TRACE_CONTEXT(VideoPlayer::setPrefinishMark, EAudioApi); + TRACE_ENTRY("state %d mark %d", m_state, mark); + Q_UNUSED(mark); // to silence warnings in release builds + + // TODO: implement prefinish mark + + TRACE_EXIT_0(); +#endif +} + +qint32 MMF::VideoPlayer::transitionTime() const +{ +#if 0 + TRACE_CONTEXT(VideoPlayer::transitionTime, EAudioApi); + TRACE_ENTRY("state %d", m_state); + + // TODO: implement transition time + const qint32 result = 0; + TRACE_RETURN("%d", result); +#endif +} + +void MMF::VideoPlayer::setTransitionTime(qint32 time) +{ +#if 0 + TRACE_CONTEXT(VideoPlayer::setTransitionTime, EAudioApi); + TRACE_ENTRY("state %d time %d", m_state, time); + Q_UNUSED(time); // to silence warnings in release builds + + // TODO: implement transition time + + TRACE_EXIT_0(); +#endif +} + + +//----------------------------------------------------------------------------- +// Volume +//----------------------------------------------------------------------------- + +qreal MMF::VideoPlayer::volume() const +{ + //return m_volume; +} + +bool MMF::VideoPlayer::setVolume(qreal volume) +{ +#if 0 + TRACE_CONTEXT(VideoPlayer::setVolume, EAudioInternal); + TRACE_ENTRY("state %d", m_state); + + bool volumeChanged = false; + + switch(m_state) + { + case GroundState: + case LoadingState: + case ErrorState: + // Do nothing + break; + + case StoppedState: + case PausedState: + case PlayingState: + case BufferingState: + { + if(volume != m_volume) + { + const int err = m_player->SetVolume(volume * m_maxVolume); + if(KErrNone == err) + { + m_volume = volume; + volumeChanged = true; + } + else + { + m_error = NormalError; + changeState(ErrorState); + } + } + break; + } + + // Protection against adding new states and forgetting to update this + // switch + default: + TRACE_PANIC(InvalidStatePanic); + } + + TRACE_RETURN("%d", volumeChanged); +#endif +} + +void MMF::VideoPlayer::setAudioOutput(AudioOutput* audioOutput) +{ + //m_audioOutput = audioOutput; +} + + +//----------------------------------------------------------------------------- +// Private functions +//----------------------------------------------------------------------------- + +qint64 MMF::VideoPlayer::toMilliSeconds(const TTimeIntervalMicroSeconds &in) +{ + //return in.Int64() / 1000; +} + +Phonon::State MMF::VideoPlayer::phononState(PrivateState state) +{ +#if 0 + const Phonon::State phononState = + GroundState == state + ? Phonon::StoppedState + : static_cast(state); + + return phononState; +#endif +} + +void MMF::VideoPlayer::changeState(PrivateState newState) +{ +#if 0 + TRACE_CONTEXT(VideoPlayer::changeState, EAudioInternal); + TRACE_ENTRY("state %d newState %d", m_state, newState); + + // TODO: add some invariants to check that the transition is valid + + const Phonon::State currentPhononState = phononState(m_state); + const Phonon::State newPhononState = phononState(newState); + if(currentPhononState != newPhononState) + { + TRACE("emit stateChanged(%d, %d)", newPhononState, currentPhononState); + emit stateChanged(newPhononState, currentPhononState); + } + + m_state = newState; + + TRACE_EXIT_0(); +#endif +} + +void MMF::VideoPlayer::tick() +{ +#if 0 + TRACE_CONTEXT(VideoPlayer::tick, EAudioInternal); + TRACE_ENTRY("state %d", m_state); + + emit tick(currentTime()); + + TRACE_EXIT_0(); +#endif +} + diff --git a/src/3rdparty/phonon/mmf/videoplayer.h b/src/3rdparty/phonon/mmf/videoplayer.h new file mode 100644 index 0000000..3ea9c1a --- /dev/null +++ b/src/3rdparty/phonon/mmf/videoplayer.h @@ -0,0 +1,163 @@ +/* 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 . + +*/ + +#ifndef PHONON_MMF_VIDEOPLAYER_H +#define PHONON_MMF_VIDEOPLAYER_H + +/* We use the extra qualification include/ to avoid picking up the include + * Phonon has. */ +#include +#include "abstractplayer.h" + +#include + +class CDrmPlayerUtility; +class TTimeIntervalMicroSeconds; +class QTimer; + +namespace Phonon +{ + namespace MMF + { + class AudioOutput; + + /** + * + * See + * How to + * play a video file using CVideoPlayerUtility + */ + class VideoPlayer : public AbstractPlayer + { + Q_OBJECT + public: + VideoPlayer(); + virtual ~VideoPlayer(); + + // AbstractPlayer + virtual void play(); + virtual void pause(); + virtual void stop(); + virtual void seek(qint64 milliseconds); + virtual qint32 tickInterval() const; + virtual void setTickInterval(qint32 interval); + virtual bool hasVideo() const; + virtual bool isSeekable() const; + virtual qint64 currentTime() const; + virtual Phonon::State state() const; + virtual QString errorString() const; + virtual Phonon::ErrorType errorType() const; + virtual qint64 totalTime() const; + virtual MediaSource source() const; + virtual void setSource(const MediaSource &); + virtual void setNextSource(const MediaSource &source); + virtual qint32 prefinishMark() const; + virtual void setPrefinishMark(qint32); + virtual qint32 transitionTime() const; + virtual void setTransitionTime(qint32); + +#ifdef QT_PHONON_MMF_AUDIO_DRM + // MDrmVideoPlayerCallback + virtual void MdapcInitComplete(TInt aError, + const TTimeIntervalMicroSeconds &aDuration); + virtual void MdapcPlayComplete(TInt aError); + + // MAudioLoadingObserver + virtual void MaloLoadingStarted(); + virtual void MaloLoadingComplete(); +#else + // MMdaVideoPlayerCallback + virtual void MapcInitComplete(TInt aError, + const TTimeIntervalMicroSeconds &aDuration); + virtual void MapcPlayComplete(TInt aError); +#endif + + qreal volume() const; + bool setVolume(qreal volume); + + void setAudioOutput(AudioOutput* audioOutput); + + Q_SIGNALS: + void totalTimeChanged(); + void stateChanged(Phonon::State oldState, + Phonon::State newState); + void finished(); + void tick(qint64 time); + + private Q_SLOTS: + /** + * Receives signal from m_tickTimer + */ + void tick(); + + private: + static qint64 toMilliSeconds(const TTimeIntervalMicroSeconds &); + + /** + * Defined private state enumeration in order to add GroundState + */ + enum PrivateState + { + LoadingState = Phonon::LoadingState, + StoppedState = Phonon::StoppedState, + PlayingState = Phonon::PlayingState, + BufferingState = Phonon::BufferingState, + PausedState = Phonon::PausedState, + ErrorState = Phonon::ErrorState, + GroundSta