diff -r 6369bfd1b60d -r 08b5eae9f9ff dlnasrv_exampleapp/src/exampleappengine_p.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dlnasrv_exampleapp/src/exampleappengine_p.cpp Wed Nov 03 11:45:09 2010 +0200 @@ -0,0 +1,1065 @@ +/* +* Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: +* +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "exampleappengine_p.h" +#include "trace.h" + +/*! + /class ExampleAppEnginePrivate + /brief Implements interface to Symbian side DLNA APIs. +*/ + +/*! + C++ constructor. +*/ +ExampleAppEnginePrivate::ExampleAppEnginePrivate(): + q_ptr(0), + mSettingsEngine(0), + mAVRenderingSession(0), + mRenderingStateMachine(0), + mVolumeStateMachine(0), + mAVController(0), + mIap(0), + mIapName(""), + mDevices(0), + mDevice(0), + mPlaybackState(ExampleAppEngine::PlaybackStateStopped), + mItemResolver(0) +{ + FUNC_LOG + + TRAP_IGNORE(mSettingsEngine = CUPnPSettingsEngine::NewL()); + + TRAP_IGNORE(mDevices = CUpnpAVDeviceList::NewL()); + + TRAP_IGNORE(mConnectionMonitor = CUPnPConnectionMonitor::NewL(0)); + mConnectionMonitor->SetObserver(*this); +} + +/*! + C++ destructor. +*/ +ExampleAppEnginePrivate::~ExampleAppEnginePrivate() +{ + FUNC_LOG + + delete mItemResolver; + + delete mDevices; + + delete mSettingsEngine; + + if (mAVRenderingSession) + { + if (mAVController) + { + mAVController->StopRenderingSession(*mAVRenderingSession); + } + } + + delete mRenderingStateMachine; + + delete mVolumeStateMachine; + + if (mAVController) + { + mAVController->Release(); + } + + delete mConnectionMonitor; +} + +/*! + description + + /a + /return +*/ +void ExampleAppEnginePrivate::construct() +{ + FUNC_LOG + + resolveIapL(); + resolveIapNameL(); +} + +/*! + description + + /a + /return +*/ +int ExampleAppEnginePrivate::getConnectedIap() const +{ + FUNC_LOG + + return mIap; +} + +/*! + description + + /a + /return +*/ +QString ExampleAppEnginePrivate::getConnectedIapName() const +{ + FUNC_LOG + + return mIapName; +} + +/*! + description + + /a + /return +*/ +int ExampleAppEnginePrivate::getPlaybackState() const +{ + FUNC_LOG + + return mPlaybackState; +} + +/*! + description + + /a + /return +*/ +bool ExampleAppEnginePrivate::isSeekSupported() const +{ + FUNC_LOG + + // TODO: return real value when seek is implemented + + return false; +} + +/*! + description + + /a + /return +*/ +bool ExampleAppEnginePrivate::isPauseSupported() const +{ + FUNC_LOG + + bool isSupported(false); + + if (mDevice) + { + isSupported = mDevice->PauseCapability(); + } + + return isSupported; +} + +/*! + description + + /a + /return +*/ +void ExampleAppEnginePrivate::searchRenderingDevices() +{ + FUNC_LOG + + if (mIap) + { + // first create av controller + if (!mAVController) + { + TRAP_IGNORE(mAVController = UPnPAVControllerFactory::NewUPnPAVControllerL()); + if (!mAVController) + { + return; + } + mAVController->SetDeviceObserver(*this); + } + + // check if devices have been found + TRAP_IGNORE(searchRenderingDevicesL()); + } +} + +/*! + description + + /a + /return +*/ +void ExampleAppEnginePrivate::prepareRenderingDevice(const QString &uuid) +{ + FUNC_LOG + + TRAP_IGNORE(prepareRenderingDeviceL(uuid)); +} + +/*! + description + + /a + /return +*/ +int ExampleAppEnginePrivate::initFile(const QString& file) +{ + FUNC_LOG + + TRAPD(err, initFileL(file)); + + return err; +} + +/*! + description + + /a + /return +*/ +void ExampleAppEnginePrivate::play() +{ + FUNC_LOG + + TRAP_IGNORE(playL()); +} + +/*! + description + + /a + /return +*/ +void ExampleAppEnginePrivate::pause() +{ + FUNC_LOG + + TRAP_IGNORE(pauseL()); +} + +/*! + description + + /a + /return +*/ +void ExampleAppEnginePrivate::stop() +{ + FUNC_LOG + + TRAP_IGNORE(stopL()); +} + +/*! + description + + /a + /return +*/ +void ExampleAppEnginePrivate::volumeUp() +{ + FUNC_LOG + + // TODO: implement +} + +/*! + description + + /a + /return +*/ +void ExampleAppEnginePrivate::volumeDown() +{ + FUNC_LOG + + // TODO: implement +} + +/*! + description + + /a + /return +*/ +void ExampleAppEnginePrivate::rew() +{ + FUNC_LOG + + // TODO: implement +} + +/*! + description + + /a + /return +*/ +void ExampleAppEnginePrivate::ff() +{ + FUNC_LOG + + // TODO: implement +} + +/*! + description + + /a + /return +*/ +void ExampleAppEnginePrivate::UPnPDeviceDiscovered(const CUpnpAVDevice& aDevice) +{ + FUNC_LOG + + TRAP_IGNORE(upnpDeviceDiscoveredL(aDevice)); +} + +/*! + description + + /a + /return +*/ +void ExampleAppEnginePrivate::UPnPDeviceDisappeared(const CUpnpAVDevice& aDevice) +{ + FUNC_LOG + + // search device from list + CUpnpAVDevice *device(NULL); + int count(mDevices->Count()); + int index(0); + for (int i = 0; i < count; i++) + { + device = (*mDevices)[i]; + if (device->Uuid() == aDevice.Uuid()) + { + index = i; + break; + } + device = NULL; + } + + // remove if device was found + if (device) + { + mDevices->Remove(index); + + if (device->Uuid() == mDevice->Uuid()) + { + stopRenderingSession(); + } + + QString name = asString8(device->FriendlyName()); + QString uuid = asString8(device->Uuid()); + emit q_ptr->renderingDeviceDisappeared(name, uuid); + + delete device; + } +} + +/*! + description + + /a + /return +*/ +void ExampleAppEnginePrivate::WLANConnectionLost() +{ + FUNC_LOG + + // no implementation required +} + +/*! + description + + /a + /return +*/ +void ExampleAppEnginePrivate::VolumeResult(TInt aError, + TInt aVolumeLevel, + TBool aActionResponse) +{ + FUNC_LOG + + if (mVolumeStateMachine) + { + mVolumeStateMachine->VolumeResult(aError, aVolumeLevel, aActionResponse); + } +} + +/*! + description + + /a + /return +*/ +void ExampleAppEnginePrivate::MuteResult(TInt aError, + TBool aMute, + TBool aActionResponse) +{ + FUNC_LOG + + if (mVolumeStateMachine) + { + mVolumeStateMachine->MuteResult(aError, aMute, aActionResponse); + } +} + +/*! + description + + /a + /return +*/ +void ExampleAppEnginePrivate::InteractOperationComplete(TInt aError, + TUPnPAVInteractOperation aOperation) +{ + FUNC_LOG + + if (mRenderingStateMachine) + { + mRenderingStateMachine->InteractOperationComplete(aError, aOperation); + } +} + +/*! + description + + /a + /return +*/ +void ExampleAppEnginePrivate::PositionInfoResult(TInt aError, + const TDesC8& aTrackPosition, + const TDesC8& aTrackLength) +{ + FUNC_LOG + + if (mRenderingStateMachine) + { + mRenderingStateMachine->PositionInfoResult(aError, aTrackPosition, aTrackLength); + } +} + +/*! + description + + /a + /return +*/ +void ExampleAppEnginePrivate::SetURIResult(TInt aError) +{ + FUNC_LOG + + if (mRenderingStateMachine) + { + mRenderingStateMachine->SetURIResult(aError); + } +} + +/*! + description + + /a + /return +*/ +void ExampleAppEnginePrivate::SetNextURIResult(TInt aError) +{ + FUNC_LOG + + if (mRenderingStateMachine) + { + mRenderingStateMachine->SetNextURIResult(aError); + } +} + +/*! + description + + /a + /return +*/ +void ExampleAppEnginePrivate::MediaRendererDisappeared(TUPnPDeviceDisconnectedReason /*aReason*/) +{ + FUNC_LOG + + // TODO: implement +} + +/*! + description + + /a + /return +*/ +void ExampleAppEnginePrivate::RendererSyncReady(TInt /*aError*/, Upnp::TState /*aState*/) +{ + FUNC_LOG + + // TODO: implement +} + +/*! + description + + /a + /return +*/ +void ExampleAppEnginePrivate::RenderingStateChanged(TInt aError, + Upnp::TState aState, + TBool /*aUserOriented*/, + TInt /*aStateParam*/) +{ + FUNC_LOG + + int state(ExampleAppEngine::PlaybackStateStopped); + + if (aError == KErrNone) + { + switch (aState) + { + case Upnp::EBuffering: + { + state = ExampleAppEngine::PlaybackStateBuffering; + break; + } + case Upnp::EPlaying: + { + state = ExampleAppEngine::PlaybackStatePlaying; + break; + } + case Upnp::EPaused: + { + state = ExampleAppEngine::PlaybackStatePaused; + break; + } + default: + { + // no actions, stopped state is used + break; + } + } + } + + mPlaybackState = state; + + emit q_ptr->stateChanged(mPlaybackState); +} + +/*! + description + + /a + /return +*/ +void ExampleAppEnginePrivate::PositionSync(TInt /*aError*/, + Upnp::TPositionMode /*aMode*/, + TInt /*aDuration*/, + TInt /*aPosition*/) +{ + FUNC_LOG + + // TODO: implement +} + +/*! + description + + /a + /return +*/ +void ExampleAppEnginePrivate::VolumeSyncReady(TInt /*aError*/) +{ + FUNC_LOG + + // TODO: implement +} + +/*! + description + + /a + /return +*/ +void ExampleAppEnginePrivate::VolumeChanged(TInt /*aError*/, + TInt /*aVolume*/, + TBool /*aUserOriented*/) +{ + FUNC_LOG + + // TODO: implement +} + +/*! + description + + /a + /return +*/ +void ExampleAppEnginePrivate::MuteChanged(TInt /*aError*/, + TBool /*aMuteState*/, + TBool /*aUserOriented*/) +{ + FUNC_LOG + + // TODO: implement +} + +/*! + description + + /a + /return +*/ +void ExampleAppEnginePrivate::ResolveComplete(const MUPnPItemResolver& /*aResolver*/, + TInt aError) +{ + FUNC_LOG + + ERROR(aError, "Error while resolving an item"); + + emit q_ptr->initComplete(aError); +} + +/*! + description + + /a + /return +*/ +void ExampleAppEnginePrivate::ConnectionLost(TBool /*aUserOriented*/) +{ + FUNC_LOG + + stopRenderingSession(); + + mIap = 0; + mIapName = "Not connected"; + + emit q_ptr->iapUpdated(mIapName); + emit q_ptr->iapUpdated(mIap); +} + +/*! + description + + /a + /return +*/ +void ExampleAppEnginePrivate::ConnectionCreated(TInt /*aConnectionId*/) +{ + FUNC_LOG + + TRAP_IGNORE(resolveIapL()); + TRAP_IGNORE(resolveIapNameL()); + + emit q_ptr->iapUpdated(mIapName); + emit q_ptr->iapUpdated(mIap); +} + +/*! + description + + /a + /return +*/ +void ExampleAppEnginePrivate::searchRenderingDevicesL() +{ + FUNC_LOG + + emit q_ptr->renderingDeviceSearchStarted(); + + CUpnpAVDeviceList *deviceList = mAVController->GetMediaRenderersL(); + int count(deviceList->Count()); + for (int i = count - 1; i >= 0; i--) + { + CUpnpAVDevice *device = (*deviceList)[i]; + upnpDeviceDiscoveredL(*device); + } + delete deviceList; +} + +/*! + description + + /a + /return +*/ +void ExampleAppEnginePrivate::upnpDeviceDiscoveredL(const CUpnpAVDevice& aDevice) +{ + FUNC_LOG + + if (aDevice.DeviceType() == CUpnpAVDevice::EMediaRenderer) + { + CUpnpAVDevice *device(0); + int count(mDevices->Count()); + for (int i = 0; i < count; i++) + { + device = (*mDevices)[i]; + if (device->Uuid() == aDevice.Uuid()) + { + // found + break; + } + device = 0; + } + + if (!device) + { + // create new device + device = CUpnpAVDevice::NewL(aDevice); + mDevices->AppendDeviceL(*device); + + QString name = asString8(device->FriendlyName()); + QString uuid = asString8(device->Uuid()); + + INFO_2("New rendering device found: Name = %s, Uuid = %s", + name.utf16(), uuid.utf16()); + + emit q_ptr->renderingDeviceFound(name, uuid); + } + } +} + +/*! + description + + /a + /return +*/ +void ExampleAppEnginePrivate::prepareRenderingDeviceL(const QString &uuid) +{ + FUNC_LOG + + // get current uuid + QString currentUuid; + if (mDevice) + { + currentUuid = asString8(mDevice->Uuid()); + } + + // check if uuid is different than the requsted one + if (currentUuid != uuid) + { + // search the rendering device + CUpnpAVDevice *device = 0; + int count(mDevices->Count()); + for (int i = 0; i < count; i++) + { + device = (*mDevices)[i]; + QString deviceUuid = asString8(device->Uuid()); + if (deviceUuid == uuid) + { + // device found + break; + } + device = 0; + } + + stopRenderingSession(); + + mDevice = device; + if (mDevice) + { + startRenderingSessionL(*mDevice); + } + } +} + +/*! + description + + /a + /return +*/ +void ExampleAppEnginePrivate::startRenderingSessionL(const CUpnpAVDevice &device) +{ + FUNC_LOG + + // start new rendering session + mAVRenderingSession = &mAVController->StartRenderingSessionL(device); + mAVRenderingSession->SetObserver(*this); + + // start new rendering state machine + mRenderingStateMachine = CUpnpRenderingStateMachine::NewL(*mAVRenderingSession); + mRenderingStateMachine->SetObserver(*this); + mRenderingStateMachine->SyncL(); + + // start new volume state machine + mVolumeStateMachine = CUpnpVolumeStateMachine::NewL(*mAVRenderingSession); + mVolumeStateMachine->SetObserver(*this); + mVolumeStateMachine->SyncL(); +} + +/*! + description + + /a + /return +*/ +void ExampleAppEnginePrivate::stopRenderingSession() +{ + FUNC_LOG + + // stop ongoing playback + if (mPlaybackState != ExampleAppEngine::PlaybackStateStopped) + { + stop(); + RenderingStateChanged(KErrNone, Upnp::EStopped, EFalse, 0); + } + + // release rendering state machine + delete mRenderingStateMachine; + mRenderingStateMachine = 0; + + // release volume state machine + delete mVolumeStateMachine; + mVolumeStateMachine = 0; + + // stop and release rendering session + if (mAVController && mAVRenderingSession) + { + mAVController->StopRenderingSession(*mAVRenderingSession); + mAVRenderingSession = 0; + } + + mDevice = 0; +} + +/*! + description + + /a + /return +*/ +void ExampleAppEnginePrivate::initFileL(const QString &file) +{ + FUNC_LOG + + delete mItemResolver; + mItemResolver = 0; + + if (mDevice) + { + TPtrC filePath(file.utf16(), file.length()); + TUPnPSelectDefaultResource selector; + mItemResolver = + UPnPItemResolverFactory::NewLocalItemResolverL( + filePath, *mAVController, selector); + mItemResolver->ResolveL(*this, mDevice); + } + else + { + // rendering device has not been selected + User::Leave(KErrNotReady); + } +} + +/*! + description + + /a + /return +*/ +bool ExampleAppEnginePrivate::isReadyForPlayback() const +{ + FUNC_LOG + + bool isReady(false); + + if (mDevice && // device is selected + mAVRenderingSession && // av rendering session is created + mRenderingStateMachine && // rendering state machine is created + mVolumeStateMachine) // volume state machine is created + { + isReady = true; + } + + return isReady; +} + +/*! + description + + /a + /return +*/ +void ExampleAppEnginePrivate::playL() +{ + FUNC_LOG + + if (isReadyForPlayback()) + { + mRenderingStateMachine->CommandL(Upnp::EPlay, 0, &mItemResolver->Item()); + } + else + { + User::Leave(KErrNotReady); + } +} + +/*! + description + + /a + /return +*/ +void ExampleAppEnginePrivate::pauseL() +{ + FUNC_LOG + + if (isReadyForPlayback()) + { + // double check that the rendering device supports pause capability + if (mDevice->PauseCapability()) + { + mRenderingStateMachine->CommandL(Upnp::EPause); + } + else + { + User::Leave(KErrNotSupported); + } + } + else + { + User::Leave(KErrNotReady); + } +} + +/*! + description + + /a + /return +*/ +void ExampleAppEnginePrivate::stopL() +{ + FUNC_LOG + + if (isReadyForPlayback()) + { + mRenderingStateMachine->CommandL(Upnp::EStop); + } + else + { + User::Leave(KErrNotReady); + } +} + +/*! + description + + /a + /return +*/ +void ExampleAppEnginePrivate::resolveIapL() +{ + FUNC_LOG + + // code below could be optimized so that connections to socket server + // are only made once + RSocketServ socketServ; + int err = socketServ.Connect(); + if (err == KErrNone) + { + RConnection connection; + err = connection.Open(socketServ); + if (err == KErrNone) + { + uint connectionCount(0); + err = connection.EnumerateConnections(connectionCount); + if (err == KErrNone && + connectionCount == 1) + { + // One active connection - find it and try using it + TPckgBuf connectionInfo; + for (int i = 1; i <= connectionCount; ++i) + { + if (connection.GetConnectionInfo(i, connectionInfo) == KErrNone) + { + // resolve iap id and name + mIap = connectionInfo().iIapId; + } + } + connection.Close(); + } + } + socketServ.Close(); + } + + mSettingsEngine->SetAccessPoint(mIap); +} + +/*! + description + + /a + /return +*/ +void ExampleAppEnginePrivate::resolveIapNameL() +{ + FUNC_LOG + + HBufC* iapName(NULL); + TRAP_IGNORE(iapName = CUPnPSettingsEngine::GetCurrentIapNameL(mIap)); + if (iapName) + { + mIapName = asString(*iapName); + delete iapName; + } +} + +/*! + description + + /a + /return +*/ +QString ExampleAppEnginePrivate::asString(const TDesC &desc) const +{ + return QString::fromUtf16(desc.Ptr(), desc.Length()); +} + +/*! + description + + /a + /return +*/ +QString ExampleAppEnginePrivate::asString8(const TDesC8 &desc) const +{ + return QString::fromUtf8((char*)desc.Ptr(), desc.Length()); +} + +// End of file