upnpavcontroller/upnpavcontrollerhelper/src/upnpremoteitemresolver.cpp
author Sampo Huttunen <sampo.huttunen@nokia.com>
Thu, 18 Nov 2010 15:46:57 +0200
branchIOP_Improvements
changeset 44 97caed2372ca
parent 38 5360b7ddc251
permissions -rw-r--r--
Fixed AVController, it was accidentally set to search only for renderers. Now also servers are added to device list. Also some minor changes in package definition xml and platform API xml definition files.

/*
* 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:      Resolver for remote items
*
*/






// INCLUDE FILES
// dlnasrv / mediaserver api
#include <upnpobject.h>
#include <upnpitem.h>
#include <upnpcontainer.h>
#include <upnpelement.h>
#include <upnpattribute.h>
#include <upnpdlnaprotocolinfo.h>

// dlnasrv / avcontroller api
#include "upnpavbrowsingsession.h" // browsing session

// dlnasrv / avcontroller helper api
#include "upnpresourceselector.h" // MUPnPResourceSelector
#include "upnpitemresolverobserver.h" // observer for this class
#include "upnpitemutility.h" // for ResourceFromItem
#include "upnpconstantdefs.h" // for browsing param: KSortNone

// dlnasrv / xmlparser api
#include "upnpxmlparser.h" // for xml parsing

// dlnasrv / avcontroller helper internal
#include "upnpremoteitemresolver.h"

_LIT( KComponentLogfile, "upnpavcontrollerhelper.txt");
#include "upnplog.h"

// CONSTANTS


// METHODS

// --------------------------------------------------------------------------
// CUPnPRemoteItemResolver::NewL
//---------------------------------------------------------------------------
CUPnPRemoteItemResolver* CUPnPRemoteItemResolver::NewL(
    const TDesC8& aItemId,
    MUPnPAVBrowsingSession& aHostSession,
    MUPnPResourceSelector& aSelector,
    const TDesC8& aBrowseFilter )
    {
    CUPnPRemoteItemResolver* self = new (ELeave) CUPnPRemoteItemResolver(
        aItemId, aHostSession, aSelector, aBrowseFilter );
    CleanupStack::PushL( self );
    self->ConstructL( aItemId, aHostSession, aSelector, aBrowseFilter );
    CleanupStack::Pop( self );
    return self;
    }


// --------------------------------------------------------------------------
// CUPnPRemoteItemResolver::CUPnPRemoteItemResolver
//---------------------------------------------------------------------------
CUPnPRemoteItemResolver::CUPnPRemoteItemResolver(
    const TDesC8& /*aItemId*/,
    MUPnPAVBrowsingSession& aHostSession,
    MUPnPResourceSelector& aSelector,
    const TDesC8& aBrowseFilter )
    : CUPnPAbstractBrowsingSessionObserver()
    , iBrowsingSession( aHostSession )
    , iSelector( aSelector )
    , iBrowseFilter( aBrowseFilter )
    {
    iState = EStateIdle;
    SetSession( aHostSession );
    }


// --------------------------------------------------------------------------
// CUPnPRemoteItemResolver::ConstructL
//---------------------------------------------------------------------------
void CUPnPRemoteItemResolver::ConstructL(
    const TDesC8& aItemId,
    MUPnPAVBrowsingSession& /*aHostSession*/,
    MUPnPResourceSelector& /*aSelector*/,
    const TDesC8& /*aBrowseFilter*/ )
    {
    iItemId = aItemId.AllocL();
    }

// --------------------------------------------------------------------------
// CUPnPRemoteItemResolver::~CUPnPRemoteItemResolver
//---------------------------------------------------------------------------
CUPnPRemoteItemResolver::~CUPnPRemoteItemResolver()
    {
    Cleanup();
    delete iItemId;
    iItemId = 0;
    }

// --------------------------------------------------------------------------
// CUPnPRemoteItemResolver::ResolveL
//---------------------------------------------------------------------------
void CUPnPRemoteItemResolver::ResolveL(
    MUPnPItemResolverObserver& aObserver, CUpnpAVDevice* /*aDevice*/ )
    {
    __LOG( "RemoteItemResolver:Resolve()" );
    __ASSERTD( iState == EStateIdle, __FILE__, __LINE__ );

    // enable receiving callbacks here
    EnableSessionObserver();

    // change state
    iObserver = &aObserver;
    iState = EStateActive;

    iRecursionDepth = 0;

    iBrowsingSession.BrowseL(
        iItemId->Des(), iBrowseFilter,
        MUPnPAVBrowsingSession::EMetadata,
        0, 1, KSortNone );

    }


// --------------------------------------------------------------------------
// CUPnPRemoteItemResolver::Item
//---------------------------------------------------------------------------
const CUpnpItem& CUPnPRemoteItemResolver::Item() const
    {
    __LOG( "RemoteItemResolver:item" );
    __ASSERTD( iState == EStateReady, __FILE__, __LINE__ );
    __ASSERTD( iFirstLevelItem, __FILE__, __LINE__ );

    return *iFirstLevelItem;
    }


// --------------------------------------------------------------------------
// CUPnPRemoteItemResolver::Resource
//---------------------------------------------------------------------------
const CUpnpElement& CUPnPRemoteItemResolver::Resource() const
    {
    __LOG( "RemoteItemResolver:Resource" );
    __ASSERTD( iState == EStateReady, __FILE__, __LINE__ );
    __ASSERTD( iResource, __FILE__, __LINE__ );

    return *iResource;
    }

// --------------------------------------------------------------------------
// CUPnPRemoteItemResolver::BrowseResponse
//---------------------------------------------------------------------------
void CUPnPRemoteItemResolver::BrowseResponse(
    const TDesC8& aBrowseResponse,
    TInt aError,
    TInt /*aMatches*/,
    TInt /*aTotalCount*/,
    const TDesC8& /*aUpdateId*/ )
    {
    __ASSERTD( iState == EStateActive, __FILE__, __LINE__ );
    __LOG1( "RemoteItemResolver:BrowseResponse(%d)", aError );

    // If the browse succeeded, parse the response and process the result
    if ( aError == KErrNone )
        {
        TRAP( aError, BrowseResponseL( aBrowseResponse ) );
        }

    // It the browse failed, or the parsing/processging of the response
    // failed, do complete.
    if( aError != KErrNone )
        {
        Complete( aError );
        }
    }

// --------------------------------------------------------------------------
// CUPnPRemoteItemResolver::BrowseResponseL
//---------------------------------------------------------------------------
//
void CUPnPRemoteItemResolver::BrowseResponseL( const TDesC8& aBrowseResponse )
    {
    __LOG( "RemoteItemResolver:BrowseResponseL" );

    // Status code
    TInt status = KErrNone;

    // Result array
    RPointerArray<CUpnpObject> array;

    // Create parser
    CUPnPXMLParser* parser = NULL;
    TRAP( status, parser = CUPnPXMLParser::NewL() );

    // If the parser was created succesfully...
    if( status == KErrNone )
        {
        CleanupStack::PushL( parser );

        // Parse the result data, and process the result object
        TRAP( status,
              parser->ParseResultDataL( array, aBrowseResponse );
              if(array.Count()!= 0 )
            	  ProcessResultObjectL( array[0] );
              else
            	  {
            	  //handle error no object
            	  Complete( KErrNotFound );
            	  }
            );

        // Clean up
        CleanupStack::PopAndDestroy( parser );
        parser = NULL;
        }

    // Empty, reset and close the array
    for( TInt i=0; i<array.Count(); i++ )
        {
        delete array[i];
        }
    array.Reset();
    array.Close();

    // If there was an error, forward the leave
    if( status != KErrNone )
        {
        User::Leave( status );
        }
    }

// --------------------------------------------------------------------------
// CUPnPRemoteItemResolver::ProcessResultObjectL
//---------------------------------------------------------------------------
void CUPnPRemoteItemResolver::ProcessResultObjectL(
    const CUpnpObject* aResult )
    {
    if ( aResult->ObjectType() != EUPnPItem )
        {
        User::Leave( KErrArgument );
        }

    // copy the item
    CUpnpItem* item = CUpnpItem::NewL();
    CleanupStack::PushL( item );
    item->CopyL( *aResult );

    // select the resource
    __LOG( "RemoteItemResolver:calling SelectResource" );
    const CUpnpElement& res =
        iSelector.SelectResourceL( *item );

    if ( iRecursionDepth == 0 )
        {
        __ASSERTD( !iFirstLevelItem, __FILE__, __LINE__ );
        CleanupStack::Pop( item );
        iFirstLevelItem = item;
        item = 0; // take ownership
        }

    HBufC8* recurringId = 0;


    if ( recurringId )
        {
        // continue recursion !
        ++iRecursionDepth;
        __LOG1( "RemoteItemResolver:ProcessResult - recur %d",
            iRecursionDepth );
        iBrowsingSession.BrowseL(
            recurringId->Des(), iBrowseFilter, 
            MUPnPAVBrowsingSession::EMetadata,
            0, 1, KSortNone );
        CleanupStack::PopAndDestroy( recurringId );
        }
    else
        {
        // finished browsing the item
        __ASSERTD( !iLastLevelItem, __FILE__, __LINE__ );
        __LOG( "RemoteItemResolver:ProcessResult - finished" );
        if ( iRecursionDepth > 0 )
            {
            // pointed object is DIFFERENT from first level object
            iLastLevelItem = CUpnpItem::NewL();
            iLastLevelItem->CopyL( *item );
            }
        iResource = &res;
        Complete( KErrNone );
        }

    if( item )
        {
        CleanupStack::PopAndDestroy( item );
        }
    }


// --------------------------------------------------------------------------
// CUPnPRemoteItemResolver::Complete
//---------------------------------------------------------------------------
void CUPnPRemoteItemResolver::Complete( TInt aError )
    {
    __ASSERTD( iState == EStateActive, __FILE__, __LINE__ );

    DisableSessionObserver();
    MUPnPItemResolverObserver& observer = *iObserver;
    iObserver = 0;
    if ( aError == KErrNone )
        {
        iState = EStateReady;
        }
    else
        {
        iState = EStateIdle;
        Cleanup();
        }

    observer.ResolveComplete( *this, aError );
    }

// --------------------------------------------------------------------------
// CUPnPRemoteItemResolver::Cleanup
//---------------------------------------------------------------------------
void CUPnPRemoteItemResolver::Cleanup()
    {
    DisableSessionObserver();

    if ( iState == EStateActive )
        {
        iBrowsingSession.CancelBrowse();
        }

    iObserver = 0;

    delete iFirstLevelItem;
    iFirstLevelItem = 0;

    delete iLastLevelItem;
    iLastLevelItem = 0;

    iResource = 0;

    iState = EStateIdle;
    }