diff options
-rw-r--r-- | src/3rdparty/phonon/mmf/abstractplayer.h | 10 | ||||
-rw-r--r-- | src/3rdparty/phonon/mmf/audioplayer.cpp | 9 | ||||
-rw-r--r-- | src/3rdparty/phonon/mmf/audioplayer.h | 8 | ||||
-rw-r--r-- | src/3rdparty/phonon/mmf/backend.cpp | 2 | ||||
-rw-r--r-- | src/3rdparty/phonon/mmf/mediaobject.cpp | 316 | ||||
-rw-r--r-- | src/3rdparty/phonon/mmf/mediaobject.h | 59 | ||||
-rw-r--r-- | src/3rdparty/phonon/mmf/utils.h | 2 | ||||
-rw-r--r-- | src/3rdparty/phonon/mmf/videoplayer.cpp | 2 | ||||
-rw-r--r-- | src/3rdparty/phonon/mmf/videoplayer.h | 24 | ||||
-rw-r--r-- | src/3rdparty/phonon/phonon/factory.cpp | 2 | ||||
-rw-r--r-- | src/plugins/phonon/mmf/mmf.pro | 3 |
11 files changed, 377 insertions, 60 deletions
diff --git a/src/3rdparty/phonon/mmf/abstractplayer.h b/src/3rdparty/phonon/mmf/abstractplayer.h index 613831a..418b896 100644 --- a/src/3rdparty/phonon/mmf/abstractplayer.h +++ b/src/3rdparty/phonon/mmf/abstractplayer.h @@ -23,6 +23,8 @@ along with this library. If not, see <http://www.gnu.org/licenses/>. #include <Phonon/phononnamespace.h> #include <Phonon/MediaSource.h> +class RFile; + namespace Phonon { namespace MMF @@ -46,7 +48,13 @@ namespace Phonon virtual Phonon::ErrorType errorType() const = 0; virtual qint64 totalTime() const = 0; virtual Phonon::MediaSource source() const = 0; - virtual void setSource(const Phonon::MediaSource &) = 0; + + // This is a temporary hack to work around KErrInUse from MMF + // client utility OpenFileL calls + //virtual void setSource(const Phonon::MediaSource &) = 0; + virtual void setFileSource + (const Phonon::MediaSource&, RFile&) = 0; + virtual void setNextSource(const Phonon::MediaSource &) = 0; virtual void setTransitionTime(qint32) = 0; diff --git a/src/3rdparty/phonon/mmf/audioplayer.cpp b/src/3rdparty/phonon/mmf/audioplayer.cpp index 106b71b..ce6a5f3 100644 --- a/src/3rdparty/phonon/mmf/audioplayer.cpp +++ b/src/3rdparty/phonon/mmf/audioplayer.cpp @@ -289,7 +289,7 @@ MediaSource MMF::AudioPlayer::source() const return m_mediaSource; } -void MMF::AudioPlayer::setSource(const MediaSource &source) +void MMF::AudioPlayer::setFileSource(const MediaSource &source, RFile& file) { TRACE_CONTEXT(AudioPlayer::setSource, EAudioApi); TRACE_ENTRY("state %d source.type %d", m_state, source.type()); @@ -311,7 +311,12 @@ void MMF::AudioPlayer::setSource(const MediaSource &source) // 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)); + //TRAP(symbianErr, m_player->OpenFileL(*filename)); + + // Open using shared filehandle + // This is a temporary hack to work around KErrInUse from MMF + // client utility OpenFileL calls + TRAP(symbianErr, m_player->OpenFileL(file)); break; } diff --git a/src/3rdparty/phonon/mmf/audioplayer.h b/src/3rdparty/phonon/mmf/audioplayer.h index 338c6fa..f573c94 100644 --- a/src/3rdparty/phonon/mmf/audioplayer.h +++ b/src/3rdparty/phonon/mmf/audioplayer.h @@ -74,7 +74,13 @@ namespace Phonon virtual Phonon::ErrorType errorType() const; virtual qint64 totalTime() const; virtual MediaSource source() const; - virtual void setSource(const MediaSource &); + + // This is a temporary hack to work around KErrInUse from MMF + // client utility OpenFileL calls + //virtual void setSource(const Phonon::MediaSource &) = 0; + virtual void setFileSource + (const Phonon::MediaSource&, RFile&); + virtual void setNextSource(const MediaSource &source); virtual qint32 prefinishMark() const; virtual void setPrefinishMark(qint32); diff --git a/src/3rdparty/phonon/mmf/backend.cpp b/src/3rdparty/phonon/mmf/backend.cpp index 3152603..8d7903e 100644 --- a/src/3rdparty/phonon/mmf/backend.cpp +++ b/src/3rdparty/phonon/mmf/backend.cpp @@ -33,7 +33,7 @@ Backend::Backend(QObject *parent) setProperty("identifier", QLatin1String("phonon_mmf")); setProperty("backendName", QLatin1String("MMF")); - setProperty("backendComment", QLatin1String("Backend using Nokia's S60 Multimedia Framework Architecture (MMF).")); + setProperty("backendComment", QLatin1String("Backend using Symbian Multimedia Framework (MMF)")); setProperty("backendVersion", QLatin1String("0.1")); setProperty("backendWebsite", QLatin1String("http://www.qtsoftware.com/")); } diff --git a/src/3rdparty/phonon/mmf/mediaobject.cpp b/src/3rdparty/phonon/mmf/mediaobject.cpp index 877e463..62dc903 100644 --- a/src/3rdparty/phonon/mmf/mediaobject.cpp +++ b/src/3rdparty/phonon/mmf/mediaobject.cpp @@ -16,10 +16,11 @@ along with this library. If not, see <http://www.gnu.org/licenses/>. */ -#include "abstractplayer.h" #include "audioplayer.h" -#include "videoplayer.h" #include "mediaobject.h" +#include "utils.h" +#include "videoplayer.h" + using namespace Phonon; using namespace Phonon::MMF; @@ -30,129 +31,361 @@ using namespace Phonon::MMF; MMF::MediaObject::MediaObject(QObject *parent) : QObject::QObject(parent) { + TRACE_CONTEXT(MediaObject::MediaObject, EAudioApi); + TRACE_ENTRY_0(); + + Q_UNUSED(parent); + + TInt err = m_recognizer.Connect(); + err = m_fileServer.Connect(); + // TODO: handle this error + + // This must be called in order to be able to share file handles with + // the recognizer server (see fileMediaType function). + err = m_fileServer.ShareProtected(); + // TODO: handle this error + + 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; + + m_file.Close(); + 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(fileName); + + m_file.Close(); + TInt err = m_file.Open(m_fileServer, *fileNameSymbian, EFileRead|EFileShareReadersOnly); + + if(KErrNone == err) + { + TDataRecognitionResult recognizerResult; + err = m_recognizer.RecognizeData(m_file, recognizerResult); + if(KErrNone == err) + { + const TPtrC mimeType = recognizerResult.iDataType.Des(); + result = mimeTypeToMediaType(mimeType); + } + } + return result; +} + + //----------------------------------------------------------------------------- // MediaObjectInterface //----------------------------------------------------------------------------- void MMF::MediaObject::play() { - m_player->play(); + if(!m_player.isNull()) + { + m_player->play(); + } } void MMF::MediaObject::pause() { - m_player->pause(); + if(!m_player.isNull()) + { + m_player->pause(); + } } void MMF::MediaObject::stop() { - m_player->stop(); + if(!m_player.isNull()) + { + m_player->stop(); + } } void MMF::MediaObject::seek(qint64 ms) { - m_player->seek(ms); + if(!m_player.isNull()) + { + m_player->seek(ms); + } } qint32 MMF::MediaObject::tickInterval() const { - return m_player->tickInterval(); + qint32 result = 0; + if(!m_player.isNull()) + { + result = m_player->tickInterval(); + } + return result; } void MMF::MediaObject::setTickInterval(qint32 interval) { - m_player->setTickInterval(interval); + if(!m_player.isNull()) + { + m_player->setTickInterval(interval); + } } bool MMF::MediaObject::hasVideo() const { - return m_player->hasVideo(); + bool result = false; + if(!m_player.isNull()) + { + result = m_player->hasVideo(); + } + return result; } bool MMF::MediaObject::isSeekable() const { - return m_player->isSeekable(); + bool result = false; + if(!m_player.isNull()) + { + result = m_player->isSeekable(); + } + return result; } Phonon::State MMF::MediaObject::state() const { - return m_player->state(); + Phonon::State result = Phonon::StoppedState; + if(!m_player.isNull()) + { + result = m_player->state(); + } + return result; } qint64 MMF::MediaObject::currentTime() const { - return m_player->currentTime(); + qint64 result = 0; + if(!m_player.isNull()) + { + result = m_player->currentTime(); + } + return result; } QString MMF::MediaObject::errorString() const { - return m_player->errorString(); + QString result; + if(!m_player.isNull()) + { + result = m_player->errorString(); + } + return result; } Phonon::ErrorType MMF::MediaObject::errorType() const { - return m_player->errorType(); + Phonon::ErrorType result = Phonon::NoError; + if(!m_player.isNull()) + { + result = m_player->errorType(); + } + return result; } qint64 MMF::MediaObject::totalTime() const { - return m_player->totalTime(); + qint64 result = 0; + if(!m_player.isNull()) + { + result = m_player->totalTime(); + } + return result; } MediaSource MMF::MediaObject::source() const { - return m_player->source(); + MediaSource result; + if(!m_player.isNull()) + { + result = m_player->source(); + } + return result; } void MMF::MediaObject::setSource(const MediaSource &source) { loadPlayer(source); - - return m_player->setSource(source); + if(!m_player.isNull()) + { + //m_player->setSource(source); + + // This is a hack to work around KErrInUse from MMF client utility + // OpenFileL calls + m_player->setFileSource(source, m_file); + } } 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))); + TRACE_CONTEXT(AudioPlayer::loadPlayer, EAudioApi); + //TRACE_ENTRY("state %d source.type %d", m_state, source.type()); + // TODO: log state + TRACE_ENTRY("source.type %d", source.type()); + + // Destroy old player object + if(!m_player.isNull()) + { + disconnect(m_player.data(), 0, this, 0); + m_player.reset(NULL); + } + + MediaType mediaType = MediaTypeUnknown; + + // Determine media type + switch(source.type()) + { + case MediaSource::LocalFile: + mediaType = fileMediaType(source.fileName()); + break; + + case MediaSource::Url: + // TODO: support detection of media type from HTTP streams + TRACE_0("Network streaming not supported yet"); + + /* + * TODO: handle error + * + m_error = NormalError; + changeState(ErrorState); + break; + */ + + case MediaSource::Invalid: + case MediaSource::Disc: + case MediaSource::Stream: + TRACE_0("Unsupported media type"); + /* + * TODO: handle error + * + m_error = NormalError; + changeState(ErrorState); + */ + break; + + case MediaSource::Empty: + TRACE_EXIT_0(); + return; + } + + switch(mediaType) + { + case MediaTypeUnknown: + TRACE_0("Media type could not be determined"); + /* + * TODO: handle error + * + m_error = NormalError; + changeState(ErrorState); + */ + break; + + case MediaTypeAudio: + m_player.reset(new AudioPlayer()); + break; + + case MediaTypeVideo: + m_player.reset(new VideoPlayer()); + break; + } + + if(!m_player.isNull()) + { + 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); + if(!m_player.isNull()) + { + m_player->setNextSource(source); + } } qint32 MMF::MediaObject::prefinishMark() const { - return m_player->prefinishMark(); + qint32 result = 0; + if(!m_player.isNull()) + { + result = m_player->prefinishMark(); + } + return result; } void MMF::MediaObject::setPrefinishMark(qint32 mark) { - m_player->setPrefinishMark(mark); + if(!m_player.isNull()) + { + m_player->setPrefinishMark(mark); + } } qint32 MMF::MediaObject::transitionTime() const { - return m_player->transitionTime(); + qint32 result = 0; + if(!m_player.isNull()) + { + result = m_player->transitionTime(); + } + return result; } void MMF::MediaObject::setTransitionTime(qint32 time) { - m_player->setTransitionTime(time); + if(!m_player.isNull()) + { + m_player->setTransitionTime(time); + } } //----------------------------------------------------------------------------- @@ -161,16 +394,29 @@ void MMF::MediaObject::setTransitionTime(qint32 time) qreal MMF::MediaObject::volume() const { - return m_player->volume(); + qreal result = 0.0; + if(!m_player.isNull()) + { + m_player->volume(); + } + return result; } bool MMF::MediaObject::setVolume(qreal volume) { - return m_player->setVolume(volume); + bool result = false; + if(!m_player.isNull()) + { + result = m_player->setVolume(volume); + } + return result; } void MMF::MediaObject::setAudioOutput(AudioOutput* audioOutput) { - m_player->setAudioOutput(audioOutput); + if(!m_player.isNull()) + { + m_player->setAudioOutput(audioOutput); + } } diff --git a/src/3rdparty/phonon/mmf/mediaobject.h b/src/3rdparty/phonon/mmf/mediaobject.h index a55b6e6..2eb70c3 100644 --- a/src/3rdparty/phonon/mmf/mediaobject.h +++ b/src/3rdparty/phonon/mmf/mediaobject.h @@ -22,6 +22,10 @@ along with this library. If not, see <http://www.gnu.org/licenses/>. #include <Phonon/MediaSource> #include <Phonon/MediaObjectInterface> #include <QScopedPointer> +#include <QTimer> + +// For recognizer +#include <apgcli.h> namespace Phonon { @@ -77,10 +81,63 @@ namespace Phonon void tick(qint64 time); private: + static qint64 toMilliSeconds(const TTimeIntervalMicroSeconds &); + +// The following has been moved into the AbstractPlayer-derived classes +// This needs to be cleaned up - at present, there is no way for this class +// to enter an error state, unless it has already constructed m_player +#if 0 + /** + * 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); + + ErrorType m_error; + PrivateState m_state; +#endif + + RApaLsSession m_recognizer; + RFs m_fileServer; + enum MediaType { MediaTypeUnknown, MediaTypeAudio, MediaTypeVideo }; + MediaType mimeTypeToMediaType(const TDesC& mimeType); + MediaType fileMediaType(const QString& fileName); + // TODO: urlMediaType function + + // Storing the file handle here to work around KErrInUse error + // from MMF player utility OpenFileL functions + RFile m_file; + + AudioOutput* m_audioOutput; + + qint32 m_tickInterval; + + QTimer* m_tickTimer; + + qreal m_volume; + int m_maxVolume; + void loadPlayer(const MediaSource &source); QScopedPointer<AbstractPlayer> m_player; - }; } } diff --git a/src/3rdparty/phonon/mmf/utils.h b/src/3rdparty/phonon/mmf/utils.h index 4b967fc..72d5472 100644 --- a/src/3rdparty/phonon/mmf/utils.h +++ b/src/3rdparty/phonon/mmf/utils.h @@ -117,6 +117,7 @@ namespace Phonon #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_0(string) { if(_tc.Enabled()) _TRACE_PRINT(_TRACE_TEXT(L ## "Phonon::MMF::%s [0x%08x] " L ## string), _tc.iFunction, _tc.iAddr); } #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) @@ -126,6 +127,7 @@ namespace Phonon #define TRACE_EXIT(string, args...) #define TRACE_RETURN(string, result) return result; #define TRACE_PANIC(code) Utils::panic(code); + #define TRACE_0(string) #define TRACE(string, args...) #endif } diff --git a/src/3rdparty/phonon/mmf/videoplayer.cpp b/src/3rdparty/phonon/mmf/videoplayer.cpp index f465c96..a1cfc3c 100644 --- a/src/3rdparty/phonon/mmf/videoplayer.cpp +++ b/src/3rdparty/phonon/mmf/videoplayer.cpp @@ -320,7 +320,7 @@ MediaSource MMF::VideoPlayer::source() const #endif } -void MMF::VideoPlayer::setSource(const MediaSource &source) +void MMF::VideoPlayer::setFileSource(const MediaSource &source, RFile&) { #if 0 TRACE_CONTEXT(VideoPlayer::setSource, EAudioApi); diff --git a/src/3rdparty/phonon/mmf/videoplayer.h b/src/3rdparty/phonon/mmf/videoplayer.h index 3ea9c1a..a880966 100644 --- a/src/3rdparty/phonon/mmf/videoplayer.h +++ b/src/3rdparty/phonon/mmf/videoplayer.h @@ -64,29 +64,19 @@ namespace Phonon virtual Phonon::ErrorType errorType() const; virtual qint64 totalTime() const; virtual MediaSource source() const; - virtual void setSource(const MediaSource &); + + // This is a temporary hack to work around KErrInUse from MMF + // client utility OpenFileL calls + //virtual void setSource(const Phonon::MediaSource &); + virtual void setFileSource + (const Phonon::MediaSource&, RFile&); + 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); diff --git a/src/3rdparty/phonon/phonon/factory.cpp b/src/3rdparty/phonon/phonon/factory.cpp index b14c2b9..5c3752a 100644 --- a/src/3rdparty/phonon/phonon/factory.cpp +++ b/src/3rdparty/phonon/phonon/factory.cpp @@ -133,7 +133,7 @@ bool FactoryPrivate::createBackend() continue; } - QStringList plugins(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 diff --git a/src/plugins/phonon/mmf/mmf.pro b/src/plugins/phonon/mmf/mmf.pro index 5ac62ad..0f00832 100644 --- a/src/plugins/phonon/mmf/mmf.pro +++ b/src/plugins/phonon/mmf/mmf.pro @@ -38,6 +38,9 @@ SOURCES += \ $$PHONON_MMF_DIR/utils.cpp \ $$PHONON_MMF_DIR/videoplayer.cpp +LIBS += -lefsrv # For file server +LIBS += -lapgrfx.lib -lapmime.lib # For recognizer + # This is needed for having the .qtplugin file properly created on Symbian. QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/phonon_backend |