dlnasrv_exampleapp/src/exampleappengine_p.cpp
branchIOP_Improvements
changeset 40 08b5eae9f9ff
child 41 b4d83ea1d6e2
--- /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 <es_sock.h>
+#include <es_enum.h>
+#include <upnpsettingsengine.h>
+#include <upnpavcontrollerfactory.h>
+#include <upnpavcontroller.h>
+#include <upnpavdevice.h>
+#include <upnpavdevicelist.h>
+#include <upnprenderingstatemachine.h>
+#include <upnpavrenderingsession.h>
+#include <upnpvolumestatemachine.h>
+#include <upnpitemresolverfactory.h>
+#include <upnpitemresolver.h>
+#include <upnpconnectionmonitor.h>
+
+#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<TConnectionInfo> 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