upnpframework/upnpcommand/src/upnptaskresourceallocator.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Thu, 17 Dec 2009 08:52:00 +0200
changeset 0 7f85d04be362
permissions -rw-r--r--
Revision: 200947 Kit: 200951

/*
* Copyright (c) 2007 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:  A class that allocates resources for a task
*
*/


// INCLUDE FILES
// upnpframework / avcontroller api
#include "upnpavcontrollerfactory.h"    // UPnPAVControllerFactory
#include "upnpavcontroller.h"           // MUPnPAVController
#include "upnpavdevice.h"               // CUpnpAVDevice
#include "upnpavbrowsingsession.h"      // MUPnPAVBrowsingSession

// upnpframework / common ui
#include "upnpcommonui.h"               // CUPnPCommonUI

// command internal
#include "upnpnotehandler.h"            // CUpnpNoteHandler
#include "upnptaskresourceallocator.h"  // myself

_LIT( KComponentLogfile, "upnpcommand.log");
#include "upnplog.h"


// --------------------------------------------------------------------------
// CUpnpTaskResourceAllocator::NewL
// --------------------------------------------------------------------------
CUpnpTaskResourceAllocator* CUpnpTaskResourceAllocator::NewL(
    CUPnPCommonUI& aCommonUI,
    TInt aMode )
    {
    CUpnpTaskResourceAllocator* self = new (ELeave)
        CUpnpTaskResourceAllocator( aCommonUI, aMode );

    return self;
    }

// --------------------------------------------------------------------------
// CUpnpTaskResourceAllocator::CUpnpTaskResourceAllocator
// --------------------------------------------------------------------------
CUpnpTaskResourceAllocator::CUpnpTaskResourceAllocator(
    CUPnPCommonUI& aCommonUI,
    TInt aMode )
    : CAsyncOneShot( EPriorityStandard )
    , iCommonUI( aCommonUI )
    {
    __LOG( "[UpnpCommand]\t CUpnpTaskResourceAllocator: constructor" );

    iState = EStateIdle;
    iErrorCode = KErrNone;
    iMode = aMode;
    iLocalMSSCompleted = EFalse;

    if ( iMode & EResourceLocalMediaServer ||
         iMode & EResourceSelectDevice )
        {
        // if any of these flags are set, AVCONTROLLER flag is mandatory.
        // assert that.
        __ASSERTD( iMode & EResourceAvController, __FILE__, __LINE__ );
        }

    if ( iMode & EResourceLocalMediaServer )
        {
        // if this flag is set, one of the device selection flags is mandatory.
        __ASSERTD( iMode & EResourceSelectDevice, __FILE__, __LINE__ );
        }

    }

// --------------------------------------------------------------------------
// CUpnpTaskResourceAllocator::~CUpnpTaskResourceAllocator
// --------------------------------------------------------------------------
CUpnpTaskResourceAllocator::~CUpnpTaskResourceAllocator()
    {
    if ( iState == EStateAllocating )
        {
        __ASSERTD( iNoteHandler, __FILE__, __LINE__ );
        
        SetErrorCode( KErrCancel );
        if ( iNoteHandler )
            {
            iNoteHandler->CloseWaitNote();
            }
        }

    Cleanup();
    }

// --------------------------------------------------------------------------
// CUpnpTaskResourceAllocator::Cleanup
// --------------------------------------------------------------------------
void CUpnpTaskResourceAllocator::Cleanup()
    {
    __LOG( "[UpnpCommand]\t CUpnpTaskResourceAllocator::Cleanup" );

    delete iSelectedDevice;
    iSelectedDevice = 0;
    
    if ( iMediaServerSession )
        {
        // Stop local file sharing (release)
        TRAPD( error, iMediaServerSession->ReleaseLocalMSServicesL() );
        if( error != KErrNone )
            {
            __LOG1( "[UpnpCommand]\t CUpnpTaskResourceAllocator::\
ReleaseLocalMSService failed %d", error );
            }
        
        // Stop observing the rendering session
        iMediaServerSession->RemoveObserver();

        // Stop session
        iAVController->StopBrowsingSession( *iMediaServerSession );
        iMediaServerSession = NULL;
        }

    if( iAVController )
        {
        iAVController->RemoveDeviceObserver();
        iAVController->Release(); // Fixes ESLX-7BMJBN
        iAVController = NULL;
        }

    }




// --------------------------------------------------------------------------
// CUpnpTaskResourceAllocator::AllocateL
// --------------------------------------------------------------------------
void CUpnpTaskResourceAllocator::AllocateL()
    {
    __LOG( "[UpnpCommand]\t CUpnpTaskResourceAllocator::AllocateL" );

    __ASSERTD( iNoteHandler, __FILE__, __LINE__ );
    
    // make CAsyncOneShot to do its trick in parallel
    Call();

    // show progress note in sync.
    iState = EStateAllocating;
    TInt status = iNoteHandler->RunConnectingWaitNote();
    SetErrorCode( status );
    iState = EStateReady;

    // progress note has exited. Monitor errors from the progress note

    // in error situation clean up resources and leave
    if ( iErrorCode != KErrNone )
        {
        iState = EStateError;
        Cleanup();
        User::Leave( iErrorCode );
        }
    }

// --------------------------------------------------------------------------
// CUpnpTaskResourceAllocator::AVController
// --------------------------------------------------------------------------
MUPnPAVController& CUpnpTaskResourceAllocator::AVController()
    {
    __ASSERT( iState == EStateReady, __FILE__, __LINE__ );
    __ASSERT( iMode & EResourceAvController, __FILE__, __LINE__ );

    return *iAVController;
    }

// --------------------------------------------------------------------------
// CUpnpTaskResourceAllocator::SelectedDevice
// --------------------------------------------------------------------------
const CUpnpAVDevice& CUpnpTaskResourceAllocator::SelectedDevice()
    {
    __ASSERT( iState == EStateReady, __FILE__, __LINE__ );
    __ASSERT( iMode & EResourceSelectDevice, __FILE__, __LINE__ );
    __ASSERT( iSelectedDevice, __FILE__, __LINE__ );

    return *iSelectedDevice;
    }


// --------------------------------------------------------------------------
// CUpnpTaskResourceAllocator::RunL
// --------------------------------------------------------------------------
void CUpnpTaskResourceAllocator::RunL()
    {
    __LOG( "[UpnpCommand]\t CUpnpTaskResourceAllocator::RunL" );

    // make sure we are still on the go
    if ( iState == EStateAllocating )
        {
        // starting of AVController
        StartAvControllerL();
        }
    else
        {
        __LOG1( "[UpnpCommand]\t CUpnpTaskResourceAllocator::RunL \
    StartAvControllerL not done in state %d", iState );
        }
    // make sure we are still on the go
    if ( iState == EStateAllocating )
        {
        // select device
        SelectDeviceL();
        }
    else
        {
        __LOG1( "[UpnpCommand]\t CUpnpTaskResourceAllocator::RunL \
    SelectDeviceL not done in state %d", iState );
        }
    // make sure we are still on the go
    if ( iState == EStateAllocating )
        {
        // start the local mediaserver
        StartLocalMediaServerL();
        }
    else
        {
        __LOG1( "[UpnpCommand]\t CUpnpTaskResourceAllocator::RunL \
    StartLocalMediaServerL not done in state %d", iState );
        }        
    // make sure we are still on the go
    if ( iState == EStateAllocating )
        {
        // if local media server was started but not yet completed,
        // wait for callback
        if ( iMode & EResourceLocalMediaServer
            && !iLocalMSSCompleted )
            {
            __LOG( "[UpnpCommand]\t CUpnpTaskResourceAllocator::RunL \
    waiting for ReserveLocalMSServicesCompleted" );
            iState = EStateWaitingForLMS;
            }
        // otherwise we are done now
        else
            {
            // close the wait note
            __ASSERTD( iNoteHandler, __FILE__, __LINE__ );
            iNoteHandler->CloseWaitNote();
            }
        }
    else
        {
        __LOG1( "[UpnpCommand]\t CUpnpTaskResourceAllocator::RunL \
    CloseWaitNote not done in state %d", iState );
        }
    }

// --------------------------------------------------------------------------
// CUpnpTaskResourceAllocator::RunError
// --------------------------------------------------------------------------
TInt CUpnpTaskResourceAllocator::RunError( TInt aError )
    {
    __LOG1( "[UpnpCommand]\t CUpnpTaskResourceAllocator::RunError: %d",
        aError );

    __ASSERTD( iNoteHandler, __FILE__, __LINE__ );
    
    // asynchronous operation leaves. store the error code and make the
    // wait note exit.
    SetErrorCode( aError );
    iNoteHandler->CloseWaitNote();
        
    return KErrNone;
    }


// --------------------------------------------------------------------------
// CUpnpTaskResourceAllocator::StartAvControllerL
// --------------------------------------------------------------------------
void CUpnpTaskResourceAllocator::StartAvControllerL()
    {
    if ( iMode & EResourceAvController )
        {
        __LOG( "[UpnpCommand]\t CUpnpTaskResourceAllocator::\
StartAvControllerL" );

        // Create new UpnpAvController client instance
        iAVController = UPnPAVControllerFactory::NewUPnPAVControllerL();

        // Register as an observer (for WLAN lost notification) 
        iAVController->SetDeviceObserver( *this );
        }
    else
        {
        __LOG( "[UpnpCommand]\t CUpnpTaskResourceAllocator::\
    AvController not started" );
        }
    }

// --------------------------------------------------------------------------
// CUpnpTaskResourceAllocator::StartLocalMediaServerL
// --------------------------------------------------------------------------
void CUpnpTaskResourceAllocator::StartLocalMediaServerL()
    {
    if ( iMode & EResourceLocalMediaServer )
        {
        __LOG( "[UpnpCommand]\t CUpnpTaskResourceAllocator::\
StartLocalMediaServerL" );

        // create a dummy device
        CUpnpAVDevice* dummyDevice = CUpnpAVDevice::NewLC();
        dummyDevice->SetUuidL( KNullDesC8 );
        dummyDevice->SetDeviceType(CUpnpAVDevice::EMediaServer);    
        // create a session for mediaserver resources keepalive
        iMediaServerSession =
            &iAVController->StartBrowsingSessionL( *dummyDevice );
        iMediaServerSession->SetObserver( *this );
        CleanupStack::PopAndDestroy( dummyDevice );
        // now reserve
        iMediaServerSession->ReserveLocalMSServicesL();
        }
    }


// --------------------------------------------------------------------------
// CUpnpTaskResourceAllocator::SelectDeviceL
// --------------------------------------------------------------------------
//
void CUpnpTaskResourceAllocator::SelectDeviceL()
    {
    if ( iMode & EResourceSelectDevice )
        {
        __LOG( "[UpnpCommand]\t CUpnpTaskResourceAllocator::SelectDeviceL" );

        TInt status = KErrNone;
        
        // decide device filters and popup title
        TUPnPDeviceTypesToSearch deviceFilter =
            EUPnPSearchAllDevices;
        TUPnPDialogTitle popupTitle = EUPnPSelectDeviceTitle;

        if ( iMode & EResourceSelectImageRenderer )
            {
            deviceFilter = EUPnPSearchRenderingDevicesWithImageCapability;
            }
        else if ( iMode & EResourceSelectCopyServer )
            {
            deviceFilter = EUPnPSearchServerDevicesWithCopyCapability;
            popupTitle = EUPnPCopyToTitle;
            }
        else if ( iMode & EResourceSelectMoveServer )
            {
            deviceFilter = EUPnPSearchServerDevicesWithCopyCapability;
            popupTitle = EUPnPMoveToTitle;
            }
        
        // Launch the device selection dialog
        CUpnpAVDevice* tempDevice = CUpnpAVDevice::NewL();
        CleanupStack::PushL( tempDevice );
        status = iCommonUI.SelectDeviceL(
                  *iAVController,
                  *tempDevice,
                  deviceFilter,
                  popupTitle );

        // Fix UpnpCommonUi return value
        if( status > 0 )
            {
            status = KErrNone;
            }

        if( status != KErrNone )
            {
            // failed
            User::Leave( status );
            }

        CleanupStack::Pop( tempDevice );
        iSelectedDevice = tempDevice;

        }
    }

// --------------------------------------------------------------------------
// CUpnpTaskResourceAllocator::SetErrorCode
// --------------------------------------------------------------------------
void CUpnpTaskResourceAllocator::SetErrorCode( TInt aErrorCode )
    {
    __LOG2( "[UpnpCommand]\t CUpnpTaskResourceAllocator::SetErrorCode \
%d -> %d", iErrorCode, aErrorCode );

    if ( iErrorCode == KErrNone )
        {
        __LOG( "error code changed");
        iErrorCode = aErrorCode;
        } 
    // if user cancelled operation, we don't need other error codes
    // so it's ok to reset old error code
    else if ( aErrorCode == KErrCancel )
        {
        __LOG( "error code reseted");
        iErrorCode = aErrorCode;
        }
    }

// ==========================================================================
// Methods for AVController device observer
// ==========================================================================
    
    
// --------------------------------------------------------------------------
// CUpnpTaskResourceAllocator::WLANConnectionLost
// --------------------------------------------------------------------------
void CUpnpTaskResourceAllocator::WLANConnectionLost()
    {
    __LOG( "[UpnpCommand]\t CUpnpTaskResourceAllocator::WLANConnectionLost" );

    if ( iState == EStateAllocating || iState == EStateWaitingForLMS )
        {
        __ASSERTD( iNoteHandler, __FILE__, __LINE__ );
        SetErrorCode( KErrDisconnected );
        iNoteHandler->CloseWaitNote();
        iState = EStateError;
        }
    }

void CUpnpTaskResourceAllocator::UPnPDeviceDiscovered(
    const CUpnpAVDevice& /*aDevice*/ )
    {
    }

void CUpnpTaskResourceAllocator::UPnPDeviceDisappeared(
    const CUpnpAVDevice& aDevice )
    {
    __ASSERTD( iNoteHandler, __FILE__, __LINE__ );
    if ( ( iState == EStateAllocating || iState == EStateWaitingForLMS )
         && iSelectedDevice != 0 )
        {
        if ( aDevice.Uuid() == iSelectedDevice->Uuid() )
            {
            __LOG( "[UpnpCommand]\t selected device lost !" );
            SetErrorCode( KErrDisconnected );
            iNoteHandler->CloseWaitNote();
            iState = EStateError;
            }
        }
    }
    
    
// ==========================================================================
// Methods for AVController browsing session observer
// ==========================================================================

// --------------------------------------------------------------------------
// CUpnpTaskResourceAllocator::ReserveLocalMSServicesCompleted
// --------------------------------------------------------------------------
void CUpnpTaskResourceAllocator::ReserveLocalMSServicesCompleted( TInt aError )
    {
    __LOG1( "[UpnpCommand]\t CUpnpTaskResourceAllocator::\
ReserveLocalMSServicesCompleted: %d", aError );

    if ( iState == EStateAllocating 
        || iState == EStateWaitingForLMS )
        {
        iLocalMSSCompleted = ETrue;
        SetErrorCode( aError );
        if ( aError == KErrNone )
            {
            iLocalMSStarted = ETrue;
            iMediaServerSession->RemoveObserver();
            }
        // allocation done, just waiting for this callback
        // close note and we are done
        if( iState == EStateWaitingForLMS )
            {
            iNoteHandler->CloseWaitNote();
            }
        }
    }


void CUpnpTaskResourceAllocator::BrowseResponse(
    const TDesC8& /*aBrowseResponse*/,
    TInt /*aError*/,
    TInt /*aMatches*/,
    TInt /*aTotalCount*/,
    const TDesC8& /*aUpdateId*/ )
    {
    }

void CUpnpTaskResourceAllocator::SearchResponse( 
    const TDesC8& /*aSearchResponse*/,
    TInt /*aError*/,
    TInt /*aMatches*/,
    TInt /*aTotalCount*/,
    const TDesC8& /*aUpdateId*/ )
    {
    }

void CUpnpTaskResourceAllocator::SearchCapabilitiesResponse( 
    TInt /*aError*/,
    const TDesC8& /*aSearchCapabilities*/ )
    {
    }

void CUpnpTaskResourceAllocator::CreateContainerResponse(
    TInt /*aError*/, 
    const TDesC8& /*aObjectId*/ )
    {
    }

void CUpnpTaskResourceAllocator::DeleteObjectResponse(
    TInt /*aError*/ )
    {
    }
 
void CUpnpTaskResourceAllocator::MediaServerDisappeared(
    TUPnPDeviceDisconnectedReason /*aReason*/ )
    {
    }



// --------------------------------------------------------------------------
// CUpnpTaskResourceAllocator::SetNoteHandlerL
// Sets the pointer to the note handler.
// --------------------------------------------------------------------------
void CUpnpTaskResourceAllocator::SetNoteHandlerL( 
                                        CUpnpNoteHandler* aNoteHandler )
    {
    // Check parameter
    if( !aNoteHandler )
        {
        User::Leave( KErrArgument );
        }

    iNoteHandler = aNoteHandler;
    }