summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRuth Sadler <ext-ruth.sadler@nokia.com>2011-01-11 10:32:46 (GMT)
committerGareth Stockwell <ext-gareth.stockwell@nokia.com>2011-01-11 13:18:56 (GMT)
commit1640acce5ca8f49c5655edffa2a1108048c5a414 (patch)
treef8697351bab1f13ded31c1f0ccef7e221b3c4b49
parentd33fd349c8a22b2e4a6d9bc1bf4defcb2a047744 (diff)
downloadQt-1640acce5ca8f49c5655edffa2a1108048c5a414.zip
Qt-1640acce5ca8f49c5655edffa2a1108048c5a414.tar.gz
Qt-1640acce5ca8f49c5655edffa2a1108048c5a414.tar.bz2
Allow IAP to be selected in Phonon MMF backend
The Phonon API does not provide any way for the client to specify which network connection should be used for streaming playback. If the application already has a connection open, using a bearer other than the default (e.g. using WiFi when the device default is GPRS), it may be desirable to use it for streaming, rather than allowing the Phonon backend to open a second connection on the default bearer. This patch adds a custom property on the Phonon::MediaObject, called InternetAccessPointName. The client can specify the IAP which Phonon should use by setting this property. Note that support for this property is only provided in the Phonon MMF backend. Task-number: QTBUG-11436 Reviewed-by: Gareth Stockwell
-rw-r--r--demos/qmediaplayer/mediaplayer.cpp43
-rw-r--r--demos/qmediaplayer/mediaplayer.h6
-rw-r--r--demos/qmediaplayer/qmediaplayer.pro2
-rw-r--r--dist/changes-4.7.27
-rw-r--r--src/3rdparty/phonon/mmf/abstractmediaplayer.cpp11
-rw-r--r--src/3rdparty/phonon/mmf/abstractmediaplayer.h2
-rw-r--r--src/3rdparty/phonon/mmf/abstractvideoplayer.cpp4
-rw-r--r--src/3rdparty/phonon/mmf/abstractvideoplayer.h2
-rw-r--r--src/3rdparty/phonon/mmf/audioplayer.cpp2
-rw-r--r--src/3rdparty/phonon/mmf/audioplayer.h2
-rw-r--r--src/3rdparty/phonon/mmf/download.cpp9
-rw-r--r--src/3rdparty/phonon/mmf/download.h4
-rw-r--r--src/3rdparty/phonon/mmf/mediaobject.cpp57
-rw-r--r--src/3rdparty/phonon/mmf/mediaobject.h7
-rw-r--r--src/plugins/phonon/mmf/mmf.pro3
-rwxr-xr-xtests/auto/mediaobject/mediaobject.pro2
-rw-r--r--tests/auto/mediaobject/tst_mediaobject.cpp187
17 files changed, 336 insertions, 14 deletions
diff --git a/demos/qmediaplayer/mediaplayer.cpp b/demos/qmediaplayer/mediaplayer.cpp
index 126031e..68752a0 100644
--- a/demos/qmediaplayer/mediaplayer.cpp
+++ b/demos/qmediaplayer/mediaplayer.cpp
@@ -46,6 +46,11 @@
#include "mediaplayer.h"
#include "ui_settings.h"
+#ifdef Q_OS_SYMBIAN
+#include <cdbcols.h>
+#include <cdblen.h>
+#include <commdb.h>
+#endif
MediaVideoWidget::MediaVideoWidget(MediaPlayer *player, QWidget *parent) :
Phonon::VideoWidget(parent), m_player(player), m_action(this)
@@ -269,6 +274,10 @@ MediaPlayer::MediaPlayer() :
fileMenu = new QMenu(this);
QAction *openFileAction = fileMenu->addAction(tr("Open &File..."));
QAction *openUrlAction = fileMenu->addAction(tr("Open &Location..."));
+#ifdef Q_OS_SYMBIAN
+ QAction *selectIAPAction = fileMenu->addAction(tr("Select &IAP..."));
+ connect(selectIAPAction, SIGNAL(triggered(bool)), this, SLOT(selectIAP()));
+#endif
QAction *const openLinkAction = fileMenu->addAction(tr("Open &RAM File..."));
connect(openLinkAction, SIGNAL(triggered(bool)), this, SLOT(openRamFile()));
@@ -949,3 +958,37 @@ void MediaPlayer::hasVideoChanged(bool bHasVideo)
m_videoWindow.setVisible(bHasVideo);
m_fullScreenAction->setEnabled(bHasVideo);
}
+
+#ifdef Q_OS_SYMBIAN
+void MediaPlayer::selectIAP()
+{
+ TRAPD(err, selectIAPL());
+ if (KErrNone != err)
+ QMessageBox::warning(this, "Phonon Mediaplayer", "Error selecting IAP", QMessageBox::Close);
+}
+
+void MediaPlayer::selectIAPL()
+{
+ QVariant currentIAPValue = m_MediaObject.property("InternetAccessPointName");
+ QString currentIAPString = currentIAPValue.toString();
+ bool ok = false;
+ CCommsDatabase *commsDb = CCommsDatabase::NewL(EDatabaseTypeIAP);
+ CleanupStack::PushL(commsDb);
+ commsDb->ShowHiddenRecords();
+ CCommsDbTableView* view = commsDb->OpenTableLC(TPtrC(IAP));
+ QStringList items;
+ TInt currentIAP = 0;
+ for (TInt l = view->GotoFirstRecord(), i = 0; l != KErrNotFound; l = view->GotoNextRecord(), i++) {
+ TBuf<KCommsDbSvrMaxColumnNameLength> iapName;
+ view->ReadTextL(TPtrC(COMMDB_NAME), iapName);
+ QString iapString = QString::fromUtf16(iapName.Ptr(), iapName.Length());
+ items << iapString;
+ if (iapString == currentIAPString)
+ currentIAP = i;
+ }
+ currentIAPString = QInputDialog::getItem(this, tr("Select Access Point"), tr("Select Access Point"), items, currentIAP, false, &ok);
+ if (ok)
+ m_MediaObject.setProperty("InternetAccessPointName", currentIAPString);
+ CleanupStack::PopAndDestroy(2); //commsDB, view
+}
+#endif
diff --git a/demos/qmediaplayer/mediaplayer.h b/demos/qmediaplayer/mediaplayer.h
index 7803321..7ddb7ae 100644
--- a/demos/qmediaplayer/mediaplayer.h
+++ b/demos/qmediaplayer/mediaplayer.h
@@ -141,12 +141,18 @@ private slots:
void showContextMenu(const QPoint& point);
void bufferStatus(int percent);
void openUrl();
+#ifdef Q_OS_SYMBIAN
+ void selectIAP();
+#endif
void openRamFile();
void configureEffect();
void hasVideoChanged(bool);
private:
bool playPauseForDialog();
+#ifdef Q_OS_SYMBIAN
+ void selectIAPL();
+#endif
QIcon playIcon;
QIcon pauseIcon;
diff --git a/demos/qmediaplayer/qmediaplayer.pro b/demos/qmediaplayer/qmediaplayer.pro
index 9407a81..d283ec8 100644
--- a/demos/qmediaplayer/qmediaplayer.pro
+++ b/demos/qmediaplayer/qmediaplayer.pro
@@ -33,5 +33,7 @@ symbian {
include($$QT_SOURCE_TREE/demos/symbianpkgrules.pri)
+ LIBS += -lCommDb
+
TARGET.CAPABILITY="NetworkServices"
}
diff --git a/dist/changes-4.7.2 b/dist/changes-4.7.2
index a18a237..d443d88 100644
--- a/dist/changes-4.7.2
+++ b/dist/changes-4.7.2
@@ -126,6 +126,13 @@ Qt for Mac OS X
-
+Qt for Symbian
+--------------
+
+ - Phonon MMF backend
+ * [QTBUG-11436] Added a MediaObject property which allows the client to
+ specify which Internet Access Point should be used for streaming.
+
Qt for Embedded Linux
---------------------
diff --git a/src/3rdparty/phonon/mmf/abstractmediaplayer.cpp b/src/3rdparty/phonon/mmf/abstractmediaplayer.cpp
index dfc5840..4f7caff 100644
--- a/src/3rdparty/phonon/mmf/abstractmediaplayer.cpp
+++ b/src/3rdparty/phonon/mmf/abstractmediaplayer.cpp
@@ -23,6 +23,9 @@ along with this library. If not, see <http://www.gnu.org/licenses/>.
#include "defs.h"
#include "mediaobject.h"
#include "utils.h"
+#include <cdbcols.h>
+#include <cdblen.h>
+#include <commdb.h>
QT_BEGIN_NAMESPACE
@@ -267,11 +270,15 @@ void MMF::AbstractMediaPlayer::open()
this, SLOT(downloadLengthChanged(qint64)));
connect(m_download, SIGNAL(stateChanged(Download::State)),
this, SLOT(downloadStateChanged(Download::State)));
- m_download->start();
+ int iap = m_parent->currentIAP();
+ TRACE("HTTP Url: Using IAP %d", iap);
+ m_download->start(iap);
}
#endif
else {
- symbianErr = openUrl(url.toString());
+ int iap = m_parent->currentIAP();
+ TRACE("Using IAP %d", iap);
+ symbianErr = openUrl(url.toString(), iap);
if (KErrNone != symbianErr)
errorMessage = tr("Error opening URL");
}
diff --git a/src/3rdparty/phonon/mmf/abstractmediaplayer.h b/src/3rdparty/phonon/mmf/abstractmediaplayer.h
index c3b4528..df0a42f 100644
--- a/src/3rdparty/phonon/mmf/abstractmediaplayer.h
+++ b/src/3rdparty/phonon/mmf/abstractmediaplayer.h
@@ -75,7 +75,7 @@ protected:
virtual int setDeviceVolume(int mmfVolume) = 0;
virtual int openFile(const QString &fileName) = 0;
virtual int openFile(RFile& file) = 0;
- virtual int openUrl(const QString& url) = 0;
+ virtual int openUrl(const QString& url, int iap) = 0;
virtual int openDescriptor(const TDesC8 &des) = 0;
virtual int bufferStatus() const = 0;
virtual void doClose() = 0;
diff --git a/src/3rdparty/phonon/mmf/abstractvideoplayer.cpp b/src/3rdparty/phonon/mmf/abstractvideoplayer.cpp
index 1ab5bae..ad4ee83 100644
--- a/src/3rdparty/phonon/mmf/abstractvideoplayer.cpp
+++ b/src/3rdparty/phonon/mmf/abstractvideoplayer.cpp
@@ -146,9 +146,9 @@ int MMF::AbstractVideoPlayer::openFile(RFile &file)
return err;
}
-int MMF::AbstractVideoPlayer::openUrl(const QString &url)
+int MMF::AbstractVideoPlayer::openUrl(const QString &url, int iap)
{
- TRAPD(err, m_player->OpenUrlL(qt_QString2TPtrC(url)));
+ TRAPD(err, m_player->OpenUrlL(qt_QString2TPtrC(url), iap));
return err;
}
diff --git a/src/3rdparty/phonon/mmf/abstractvideoplayer.h b/src/3rdparty/phonon/mmf/abstractvideoplayer.h
index 3bc5c7c..21446d2 100644
--- a/src/3rdparty/phonon/mmf/abstractvideoplayer.h
+++ b/src/3rdparty/phonon/mmf/abstractvideoplayer.h
@@ -66,7 +66,7 @@ public:
virtual int setDeviceVolume(int mmfVolume);
virtual int openFile(const QString &fileName);
virtual int openFile(RFile &file);
- virtual int openUrl(const QString &url);
+ virtual int openUrl(const QString &url, int iap);
virtual int openDescriptor(const TDesC8 &des);
virtual int bufferStatus() const;
virtual void doClose();
diff --git a/src/3rdparty/phonon/mmf/audioplayer.cpp b/src/3rdparty/phonon/mmf/audioplayer.cpp
index dc5c800..2ae6a3d 100644
--- a/src/3rdparty/phonon/mmf/audioplayer.cpp
+++ b/src/3rdparty/phonon/mmf/audioplayer.cpp
@@ -134,7 +134,7 @@ int MMF::AudioPlayer::openFile(RFile& file)
return err;
}
-int MMF::AudioPlayer::openUrl(const QString& /*url*/)
+int MMF::AudioPlayer::openUrl(const QString& /*url*/, int /*iap*/)
{
// Streaming playback is generally not supported by the implementation
// of the audio player API, so we use CVideoPlayerUtility for both
diff --git a/src/3rdparty/phonon/mmf/audioplayer.h b/src/3rdparty/phonon/mmf/audioplayer.h
index cf4f6d5..e963c26 100644
--- a/src/3rdparty/phonon/mmf/audioplayer.h
+++ b/src/3rdparty/phonon/mmf/audioplayer.h
@@ -67,7 +67,7 @@ typedef CMdaAudioPlayerUtility NativePlayer;
virtual int setDeviceVolume(int mmfVolume);
virtual int openFile(const QString &fileName);
virtual int openFile(RFile& file);
- virtual int openUrl(const QString& url);
+ virtual int openUrl(const QString& url, int iap);
virtual int openDescriptor(const TDesC8 &des);
virtual int bufferStatus() const;
virtual void doClose();
diff --git a/src/3rdparty/phonon/mmf/download.cpp b/src/3rdparty/phonon/mmf/download.cpp
index 7b80e4a..de65811 100644
--- a/src/3rdparty/phonon/mmf/download.cpp
+++ b/src/3rdparty/phonon/mmf/download.cpp
@@ -20,6 +20,7 @@ along with this library. If not, see <http://www.gnu.org/licenses/>.
#include "utils.h"
#include <QtCore/QDir>
#include <QtCore/private/qcore_symbian_p.h>
+#include <mmf/common/mmfcontrollerframeworkbase.h>
QT_BEGIN_NAMESPACE
@@ -43,7 +44,7 @@ DownloadPrivate::~DownloadPrivate()
m_downloadManager.Close();
}
-bool DownloadPrivate::start()
+bool DownloadPrivate::start(int iap)
{
TRACE_CONTEXT(DownloadPrivate::start, EVideoApi);
Q_ASSERT(!m_download);
@@ -54,6 +55,8 @@ bool DownloadPrivate::start()
TRACE("connect err %d", err);
if (KErrNone == err) {
// Start download
+ if (KUseDefaultIap != iap)
+ m_downloadManager.SetIntAttribute(EDlMgrIap, iap);
QHBufC url(m_parent->sourceUrl().toString());
TPtr8 url8 = url->Des().Collapse();
TRAP(err, m_download = &m_downloadManager.CreateDownloadL(url8));
@@ -140,12 +143,12 @@ const QString &Download::targetFileName() const
return m_targetFileName;
}
-void Download::start()
+void Download::start(int iap)
{
TRACE_CONTEXT(Download::start, EVideoApi);
TRACE_ENTRY_0();
Q_ASSERT(Idle == m_state);
- const bool ok = m_private->start();
+ const bool ok = m_private->start(iap);
setState(ok ? Initializing : Error);
TRACE_EXIT_0();
}
diff --git a/src/3rdparty/phonon/mmf/download.h b/src/3rdparty/phonon/mmf/download.h
index bda7963..2ce54a8 100644
--- a/src/3rdparty/phonon/mmf/download.h
+++ b/src/3rdparty/phonon/mmf/download.h
@@ -43,7 +43,7 @@ class DownloadPrivate : public QObject
public:
DownloadPrivate(Download *parent);
~DownloadPrivate();
- bool start();
+ bool start(int iap);
void resume();
signals:
void error();
@@ -69,7 +69,7 @@ public:
~Download();
const QUrl &sourceUrl() const;
const QString &targetFileName() const;
- void start();
+ void start(int iap);
void resume();
enum State {
diff --git a/src/3rdparty/phonon/mmf/mediaobject.cpp b/src/3rdparty/phonon/mmf/mediaobject.cpp
index 2c7a7ef..9da94ee 100644
--- a/src/3rdparty/phonon/mmf/mediaobject.cpp
+++ b/src/3rdparty/phonon/mmf/mediaobject.cpp
@@ -36,6 +36,10 @@ along with this library. If not, see <http://www.gnu.org/licenses/>.
#include <QDir>
#include <QResource>
#include <QUrl>
+#include <cdbcols.h>
+#include <cdblen.h>
+#include <commdb.h>
+#include <mmf/common/mmfcontrollerframeworkbase.h>
QT_BEGIN_NAMESPACE
@@ -64,7 +68,8 @@ MMF::MediaObject::MediaObject(QObject *parent) : MMF::MediaNode::MediaNode(paren
const int err = m_fileServer.Connect();
QT_TRAP_THROWING(User::LeaveIfError(err));
- Q_UNUSED(parent);
+ parent->installEventFilter(this);
+ m_iap = KUseDefaultIap;
TRACE_EXIT_0();
}
@@ -74,6 +79,7 @@ MMF::MediaObject::~MediaObject()
TRACE_CONTEXT(MediaObject::~MediaObject, EAudioApi);
TRACE_ENTRY_0();
+ parent()->removeEventFilter(this);
delete m_resource;
if (m_file)
@@ -493,6 +499,55 @@ void MMF::MediaObject::switchToNextSource()
}
//-----------------------------------------------------------------------------
+// IAP support
+//-----------------------------------------------------------------------------
+
+int MMF::MediaObject::currentIAP() const
+{
+ return m_iap;
+}
+
+bool MMF::MediaObject::eventFilter(QObject *watched, QEvent *event)
+{
+ if (event->type() == QEvent::DynamicPropertyChange ) {
+ QDynamicPropertyChangeEvent* dynamicEvent = static_cast<QDynamicPropertyChangeEvent*>(event);
+ if (dynamicEvent->propertyName() == "InternetAccessPointName") {
+ QVariant value = watched->property("InternetAccessPointName");
+ if (value.isValid()) {
+ QString iapName = value.toString();
+ TRAPD(err, setIAPIdFromNameL(iapName));
+ if (err)
+ m_player->setError(tr("Failed to set requested IAP"), err);
+ }
+ }
+ }
+ return false;
+}
+
+void MMF::MediaObject::setIAPIdFromNameL(const QString& iapString)
+{
+ TRACE_CONTEXT(MediaObject::getIapIdFromName, EVideoInternal);
+ TBuf<KCommsDbSvrMaxColumnNameLength> iapDes = qt_QString2TPtrC(iapString);
+ CCommsDatabase *commsDb = CCommsDatabase::NewL(EDatabaseTypeIAP);
+ CleanupStack::PushL(commsDb);
+ commsDb->ShowHiddenRecords();
+ CCommsDbTableView *view = commsDb->OpenTableLC(TPtrC(IAP));
+ for (TInt l = view->GotoFirstRecord(); l != KErrNotFound; l = view->GotoNextRecord()) {
+ TBuf<KCommsDbSvrMaxColumnNameLength> iapName;
+ view->ReadTextL(TPtrC(COMMDB_NAME), iapName);
+ TRACE("found IAP %S", &iapName);
+ if (iapName.CompareF(iapDes) == 0) {
+ TUint32 uiap;
+ view->ReadUintL(TPtrC(COMMDB_ID), uiap);
+ TRACE("matched IAP %S, setting m_iap %d", &iapName, uiap);
+ m_iap = uiap;
+ break;
+ }
+ }
+ CleanupStack::PopAndDestroy(2); // commsDb, view
+}
+
+//-----------------------------------------------------------------------------
// Other private functions
//-----------------------------------------------------------------------------
diff --git a/src/3rdparty/phonon/mmf/mediaobject.h b/src/3rdparty/phonon/mmf/mediaobject.h
index 5d785fb..0ed70ff 100644
--- a/src/3rdparty/phonon/mmf/mediaobject.h
+++ b/src/3rdparty/phonon/mmf/mediaobject.h
@@ -23,6 +23,7 @@ along with this library. If not, see <http://www.gnu.org/licenses/>.
#include <phonon/mediaobjectinterface.h>
#include <QScopedPointer>
#include <QTimer>
+#include <QString>
// For recognizer
#include <apgcli.h>
@@ -92,6 +93,7 @@ public:
int openFileHandle(const QString &fileName);
RFile* file() const;
QResource* resource() const;
+ int currentIAP() const;
public Q_SLOTS:
void volumeChanged(qreal volume);
@@ -113,6 +115,9 @@ Q_SIGNALS:
void finished();
void tick(qint64 time);
+protected:
+ bool eventFilter(QObject *watched, QEvent *event);
+
private Q_SLOTS:
void handlePrefinishMarkReached(qint32);
@@ -120,6 +125,7 @@ private:
void switchToSource(const MediaSource &source);
void createPlayer(const MediaSource &source);
bool openRecognizer();
+ void setIAPIdFromNameL(const QString& iapString);
// Audio / video media type recognition
MediaType fileMediaType(const QString& fileName);
@@ -143,6 +149,7 @@ private:
QResource* m_resource;
QScopedPointer<AbstractPlayer> m_player;
+ int m_iap;
};
}
diff --git a/src/plugins/phonon/mmf/mmf.pro b/src/plugins/phonon/mmf/mmf.pro
index 5d7b61d..de00c9e 100644
--- a/src/plugins/phonon/mmf/mmf.pro
+++ b/src/plugins/phonon/mmf/mmf.pro
@@ -127,6 +127,9 @@ symbian {
# These are for effects.
LIBS += -lAudioEqualizerEffect -lBassBoostEffect -lDistanceAttenuationEffect -lDopplerbase -lEffectBase -lEnvironmentalReverbEffect -lListenerDopplerEffect -lListenerLocationEffect -lListenerOrientationEffect -lLocationBase -lLoudnessEffect -lOrientationBase -lSourceDopplerEffect -lSourceLocationEffect -lSourceOrientationEffect -lStereoWideningEffect
+ # This is to allow IAP to be specified
+ LIBS += -lCommDb
+
# This is needed for having the .qtplugin file properly created on Symbian.
QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/phonon_backend
diff --git a/tests/auto/mediaobject/mediaobject.pro b/tests/auto/mediaobject/mediaobject.pro
index e887df4..1fc76a2 100755
--- a/tests/auto/mediaobject/mediaobject.pro
+++ b/tests/auto/mediaobject/mediaobject.pro
@@ -18,5 +18,7 @@ symbian:{
addFiles.sources = media/test.sdp
addFiles.path = media
DEPLOYMENT += addFiles
+ LIBS += -lCommDb -lconnmon
+ TARGET.CAPABILITY += "NetworkServices"
}
diff --git a/tests/auto/mediaobject/tst_mediaobject.cpp b/tests/auto/mediaobject/tst_mediaobject.cpp
index 5decbe2..a4ee3ba 100644
--- a/tests/auto/mediaobject/tst_mediaobject.cpp
+++ b/tests/auto/mediaobject/tst_mediaobject.cpp
@@ -101,6 +101,70 @@ const qint64 ALLOWED_TIME_FOR_SEEKING = 1000; // 1s
const qint64 SEEKING_TOLERANCE = 0;
#endif //Q_OS_WINCE
+#ifdef Q_OS_SYMBIAN
+#include <cdbcols.h>
+#include <cdblen.h>
+#include <commdb.h>
+#include <rconnmon.h>
+
+const QString KDefaultIAP = QLatin1String("default");
+const QString KInvalidIAP = QLatin1String("invalid IAP");
+
+class CConnectionObserver : public CBase, public MConnectionMonitorObserver
+{
+public:
+ static CConnectionObserver* NewL()
+ {
+ CConnectionObserver* self = new (ELeave) CConnectionObserver();
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ return self;
+ }
+ QString currentIAP()
+ {
+ return m_currentIAPName;
+ }
+ ~CConnectionObserver()
+ {
+ m_connMon.Close();
+ }
+private:
+ CConnectionObserver()
+ {
+ }
+ void ConstructL()
+ {
+ m_connMon.ConnectL();
+ m_connMon.NotifyEventL(*this);
+ }
+ void EventL (const CConnMonEventBase &aConnEvent)
+ {
+ TInt event = aConnEvent.EventType();
+ TUint connId = aConnEvent.ConnectionId();
+ TRequestStatus status;
+ switch (event) {
+ case EConnMonCreateConnection: {
+ TBuf<KCommsDbSvrMaxColumnNameLength> iapName;
+ m_connMon.GetStringAttribute(connId, 0, KIAPName, iapName, status);
+ User::WaitForRequest(status);
+ m_currentIAPName = QString(reinterpret_cast<const QChar *>(iapName.Ptr()), iapName.Length());
+ qDebug() << "A new connection created using: " << m_currentIAPName;
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+private:
+ RConnectionMonitor m_connMon;
+ QString m_currentIAPName;
+};
+
+#endif
+
+
class tst_MediaObject : public QObject
{
Q_OBJECT
@@ -140,6 +204,8 @@ class tst_MediaObject : public QObject
void pauseToPlay();
void pauseToStop();
void playSDP();
+ void playUrl_data();
+ void playUrl();
void testPrefinishMark();
void testSeek();
@@ -161,6 +227,10 @@ class tst_MediaObject : public QObject
Phonon::MediaObject *m_media;
QSignalSpy *m_stateChangedSignalSpy;
QString m_tmpFileName;
+#ifdef Q_OS_SYMBIAN
+ CConnectionObserver *m_iapConnectionObserver;
+ QString getValidIAPL();
+#endif //Q_OS_SYMBIAN
static void copyMediaFile(const QString &original,
const QString &name,
@@ -451,6 +521,10 @@ void tst_MediaObject::initTestCase()
QCOMPARE(m_media->outputPaths().size(), 1);
QCOMPARE(audioOutput->inputPaths().size(), 1);
+#ifdef Q_OS_SYMBIAN
+ TRAP_IGNORE(m_iapConnectionObserver = CConnectionObserver::NewL());
+#endif //Q_OS_SYMBIAN
+
}
void tst_MediaObject::checkForDefaults()
@@ -586,6 +660,115 @@ void tst_MediaObject::playSDP()
#endif
}
+/*!
+ Attempt to play from an RTSP link, and, on Symbian, to specify the IAP that
+ should be used to connect to the network. This test requires the unit under test
+ to have a default internet connection that will support streaming media, and ideally
+ one other internet connection that will also support streaming.
+ */
+void tst_MediaObject::playUrl_data()
+{
+ QTest::addColumn<QUrl>("url");
+ QTest::addColumn<QString>("iap");
+
+ QUrl rtspLink("rtsp://v1.cache8.c.youtube.com/CjgLENy73wIaLwnoDBCE7tF7fxMYESARFEIJbXYtZ29vZ2xlSARSB3Jlc3VsdHNgpbWqq7L7je5KDA==/0/0/0/video.3gp");
+ QUrl httpLink("http://www.theflute.co.uk/media/BachCPE_SonataAmin_1.wma");
+
+ QTest::newRow("default_IAP_rtsp") << rtspLink << KDefaultIAP;
+ QTest::newRow("invalid_IAP_rtsp") << rtspLink << KInvalidIAP;
+ //don't test HTTP link with invalid or default IAP as it will prompt the user
+
+#ifdef Q_OS_SYMBIAN
+ //Add tests with a valid IAP if we can get one from CommsDB
+ QString validIAP;
+ TRAPD(err, validIAP = getValidIAPL());
+ if (KErrNone == err) {
+ QTest::newRow("valid_IAP_rtsp") << rtspLink << validIAP;
+ QTest::newRow("valid_IAP_http") << httpLink << validIAP;
+ }
+#endif //Q_OS_SYMBIAN
+}
+
+#ifdef Q_OS_SYMBIAN
+QString tst_MediaObject::getValidIAPL()
+{
+ CCommsDatabase* commsDb = CCommsDatabase::NewL(EDatabaseTypeIAP);
+ CleanupStack::PushL(commsDb);
+ commsDb->ShowHiddenRecords();
+ CCommsDbTableView* view = commsDb->OpenTableLC(TPtrC(IAP));
+ QString validIAP;
+ TBool found = EFalse;
+ TInt record = view->GotoFirstRecord();
+ while (KErrNotFound != record) {
+ TBuf<KCommsDbSvrMaxColumnNameLength> iapName;
+ view->ReadTextL(TPtrC(COMMDB_NAME), iapName);
+ validIAP = QString::fromUtf16(iapName.Ptr(),iapName.Length());
+ //We don't want the "Easy WLAN" IAP as it will try and prompt the user
+ if ("Easy WLAN" != validIAP) {
+ qDebug() << "playUrl_data() adding a valid IAP test: " << validIAP;
+ found = ETrue;
+ break;
+ }
+ record = view->GotoNextRecord();
+ }
+ CleanupStack::PopAndDestroy(2);
+ if (!found)
+ User::Leave(KErrNotFound);
+ return validIAP;
+}
+#endif //Q_OS_SYMBIAN
+
+void tst_MediaObject::playUrl()
+{
+ QFETCH(QUrl, url);
+ QFETCH(QString, iap);
+ MediaObject media(this);
+
+ //Create a proper media path for video and audio
+ VideoWidget videoOutput;
+ Path path = createPath(&media, &videoOutput);
+ QVERIFY(path.isValid());
+ AudioOutput audioOutput(Phonon::MusicCategory, this);
+ path = createPath(&media, &audioOutput);
+ QVERIFY(path.isValid());
+
+#ifdef Q_OS_SYMBIAN
+ //The Symbian backend allows the IAP used for streaming connections to be specified
+ //by the application, using the "InternetAccessPointName" property.
+ if (KDefaultIAP != iap)
+ media.setProperty("InternetAccessPointName", iap);
+#endif //Q_OS_SYMBIAN
+ media.setCurrentSource(Phonon::MediaSource(url));
+ QVERIFY(media.state() != Phonon::ErrorState);
+
+ //we use a long 30s timeout here as it can take a long time for the streaming source to
+ //be sucessfully prepared depending on the network.
+ if (media.state() != Phonon::StoppedState)
+ QTest::waitForSignal(&media, SIGNAL(stateChanged(Phonon::State, Phonon::State)), 30000);
+ QCOMPARE(media.state(), Phonon::StoppedState);
+
+ media.play();
+ if (media.state() != Phonon::PlayingState)
+ QTest::waitForSignal(&media, SIGNAL(stateChanged(Phonon::State, Phonon::State)), 15000);
+ QCOMPARE(media.state(), Phonon::PlayingState);
+
+ //sleep and allow some of the stream to be played
+ QTest::qSleep(10000);
+
+#ifdef Q_OS_SYMBIAN
+ // Verify that the specified IAP is actually being used when we're not doing negative tests
+ if ((KDefaultIAP == iap || KInvalidIAP == iap) == false) {
+ if (m_iapConnectionObserver)
+ QCOMPARE(iap,m_iapConnectionObserver->currentIAP());
+ }
+#endif //Q_OS_SYMBIAN
+
+ media.stop();
+ if (media.state() != Phonon::StoppedState)
+ QTest::waitForSignal(&media, SIGNAL(stateChanged(Phonon::State, Phonon::State)), 15000);
+ QCOMPARE(media.state(), Phonon::StoppedState);
+}
+
void tst_MediaObject::testPrefinishMark()
{
const qint32 requestedPrefinishMarkTime = 2000;
@@ -937,6 +1120,10 @@ void tst_MediaObject::cleanupTestCase()
if (!m_tmpFileName.isNull()) {
QVERIFY(QFile::remove(m_tmpFileName));
}
+#ifdef Q_OS_SYMBIAN
+ if (m_iapConnectionObserver)
+ delete m_iapConnectionObserver;
+#endif //Q_OS_SYMBIAN
}
void tst_MediaObject::_testOneSeek(qint64 seekTo)