upnpframework/upnpmusicadapter/src/upnpbrowseplaylistfiller.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) 2006 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:  Fills MPX playlist by browsing media server content
*
*/


// INCLUDE FILES
// upnp stack api
#include <upnpobject.h>

// MPX framework api
#include <mpxcollectionutility.h>
#include <mpxmediaarray.h>
#include <mpxmediageneraldefs.h>
#include <mpxmediacontainerdefs.h>

// upnpframework / avcontroller api
#include "upnpavcontroller.h"
#include "upnpavdevice.h"
#include "upnpavbrowsingsession.h"

// upnpframework / avcontroller helper api
#include "upnpconstantdefs.h" // for browse filters

// upnpframework / xmlparser api
#include "upnpxmlparser.h"

// musicadapter internal
#include "upnpmusicadapter.h"
#include "upnpbrowseplaylistfiller.h"

// debug
_LIT16( KComponentLogfile, "musicadapter.txt" );
#include "upnplog.h"

// CONSTANTS
const TInt KBrowseRequestedCount = 100;
const TUid KHostAppUid = { 0x10208A0A };  // Host app UID
const TInt KMaxPlaylistSize = 500; // MAX container size to play
const TInt KBrowsePeriod = 5000000; // 5 seconds

// ======== MEMBER FUNCTIONS ========

// --------------------------------------------------------------------------
// CUPnPBrowsePlaylistFiller::NewL
// static constructor.
// --------------------------------------------------------------------------
//
EXPORT_C CUPnPBrowsePlaylistFiller* CUPnPBrowsePlaylistFiller::NewL( 
    const TDesC8& aContainerId,
    TInt aCachedStartIndex,
    TInt aTotalContainerSize )
    {
    __LOG( "CUPnPBrowsePlaylistFiller::NewL" );
    
    CUPnPBrowsePlaylistFiller* self = new(ELeave)
        CUPnPBrowsePlaylistFiller();
    CleanupStack::PushL( self );
    self->ConstructL( aContainerId, aCachedStartIndex, aTotalContainerSize );
    CleanupStack::Pop( self );
    return self;
    }

// --------------------------------------------------------------------------
// CUPnPBrowsePlaylistFiller::CUPnPBrowsePlaylistFiller
// 1st phase constructor.
// --------------------------------------------------------------------------
//
CUPnPBrowsePlaylistFiller::CUPnPBrowsePlaylistFiller()
    : CUPnPPlayListFiller()
    {
    }

// --------------------------------------------------------------------------
// CUPnPBrowsePlaylistFiller::ConstructL
// 2nd phase constructor.
// --------------------------------------------------------------------------
// 
void CUPnPBrowsePlaylistFiller::ConstructL(
    const TDesC8& aContainerId,
    TInt aCachedStartIndex,
    TInt aTotalContainerSize )
    {
    // Create timer for continue browse after short period.
    iBrowseTimer = CUPnPBrowseTimer::NewL( *this, KBrowsePeriod );
    iBlocksize = KBrowseRequestedCount;
    
    iContainerId = HBufC8::NewL( aContainerId.Length() );
    iContainerId->Des().Copy( aContainerId );    
    iCachedStartIndex = aCachedStartIndex;

    iPlaylistInitialSize = KErrUnknown;
    if ( aTotalContainerSize >= 0 )
        {
        iPlaylistInitialSize = Min(
            aTotalContainerSize - iCachedStartIndex,
            KMaxPlaylistSize );
        }
    iPlaylistActualSize = 0;
    }

// --------------------------------------------------------------------------
// CUPnPBrowsePlaylistFiller::~CUPnPBrowsePlaylistFiller
// Destructor.
// --------------------------------------------------------------------------
//
EXPORT_C CUPnPBrowsePlaylistFiller::~CUPnPBrowsePlaylistFiller()
    {
    delete iBrowseTimer;
    iBrowseTimer = 0;

    __LOG( "CUPnPBrowsePlaylistFiller::~CUPnPBrowsePlaylistFiller" );
    if ( iBrowsingSession )
        {
        Host().AVController().StopBrowsingSession( *iBrowsingSession );
        iBrowsingSession = 0;
        }
    delete iContainerId;
    }

// --------------------------------------------------------------------------
// CUPnPBrowsePlaylistFiller::FillL
// Fill track data into the playlist and continue browsing
// --------------------------------------------------------------------------
//    
void CUPnPBrowsePlaylistFiller::FillL(
    CUPnPMusicAdapter& aHost,
    CMPXMediaArray& aPlaylist )
    {
    __LOG( "CUPnPBrowsePlaylistFiller::Fill" );
    
    SetHost( aHost );

    // fill the initial items, increase the index
    iCurrentIndex = iCachedStartIndex;
    iPlaylistActualSize = DoFillL( aPlaylist, ObjectArray() );
    iCurrentIndex += ObjectArray().Count();

    if ( iPlaylistActualSize < iPlaylistInitialSize )
        {
        // Start doing more browse requests after short waiting period
        iBrowseTimer->Start();
        }
    else
        {
        __LOG( "CUPnPBrowsePlaylistFiller::Fill - \
        No need to browse" );
        DoComplete();
        }
    }

// --------------------------------------------------------------------------
// CUPnPBrowsePlaylistFiller::CancelFill
// Fill track data into the playlist and continue browsing
// --------------------------------------------------------------------------
//    
void CUPnPBrowsePlaylistFiller::CancelFill()
    {
    if ( iBrowsingSession )
        {
        iBrowsingSession->CancelBrowse();
        }
    }

// --------------------------------------------------------------------------
// CUPnPPlayListFiller::PlaylistSize
// Returns the total playlist size
// --------------------------------------------------------------------------
//
TInt CUPnPBrowsePlaylistFiller::PlaylistSize()
    {
    if ( iPlaylistInitialSize >= 0 )
        {
        return iPlaylistInitialSize;
        }
    else
        {
        return ObjectArray().Count();
        }
    }

// --------------------------------------------------------------------------
// Methods from MUPnPAVBrowsingSessionObserver
// --------------------------------------------------------------------------

// --------------------------------------------------------------------------
// CUPnPBrowsePlaylistFiller::BrowseResponse
// --------------------------------------------------------------------------
// 
void CUPnPBrowsePlaylistFiller::BrowseResponse(
    const TDesC8& aBrowseResponse, TInt aError, TInt /*aMatches*/,
    TInt aTotalCount, const TDesC8& /*aUpdateId*/ )
    {
    __LOG( "CUPnPBrowsePlaylistFiller::BrowseResponse" );
    TBool continueBrowse = ETrue;

    // Stop browsing if any error in previous browse 
    if( aError != KErrNone )
        {
        // Browse stops to an error - do not continue playlist.
        __LOG( "CUPnPBrowsePlaylistFiller::BrowseResponse ->error!" );
        continueBrowse = EFalse;
        DoComplete();
        }
    else 
        {
        __LOG( "CUPnPBrowsePlaylistFiller::BrowseResponse - \
            Error None" );

        TInt error = KErrNone;
        TRAP( error, AddMediaToCollectionL( aBrowseResponse ) );
        if( error != KErrNone )
            {
            __LOG( "CUPnPBrowsePlaylistFiller::BrowseResponse - \
            AddMediaToCollectionL leaves!" );
            continueBrowse = EFalse;
            DoComplete();
            }
        else
            {
            if ( iPlaylistActualSize >= iPlaylistInitialSize )
                {
                // browse is complete
                __LOG( "CUPnPBrowsePlaylistFiller::BrowseResult - \
                    ->playlist size reached." );
                continueBrowse = EFalse;
                DoComplete();
                }

            if ( iCurrentIndex >= aTotalCount )
                {
                // browse is complete
                __LOG( "CUPnPBrowsePlaylistFiller::BrowseResult - \
                    ->end of data." );
                continueBrowse = EFalse;
                DoComplete();
                }
            }     
        }

    if ( continueBrowse )
        {
        // Calculate item count to be browsed.
        iBlocksize = KBrowseRequestedCount;
        if ( iPlaylistActualSize + iBlocksize > iPlaylistInitialSize )
            {
            iBlocksize = iPlaylistInitialSize - iPlaylistActualSize;
            }

        // Continue the browse request            
        iBrowseTimer->Continue();
        }
    }

// --------------------------------------------------------------------------
// CUPnPBrowsePlaylistFiller::AddMediaToCollectionL
// Adds media to collection
// --------------------------------------------------------------------------
//    
void CUPnPBrowsePlaylistFiller::AddMediaToCollectionL( 
    const TDesC8& aBrowseResponse )
    {
    CUPnPXMLParser* parser = NULL;
    parser = CUPnPXMLParser::NewL();
    CleanupStack::PushL( parser );
    RPointerArray<CUpnpObject> array;
    parser->ParseResultDataL( array, aBrowseResponse );
       
    // Update playlist counter
    iCurrentIndex += KBrowseRequestedCount;
  
    TInt count = array.Count();    
    if( count > 0 )
        {
        // Create new media object
        CMPXMedia* media = CMPXMedia::NewL(); 
        CleanupStack::PushL( media );
        // Set collection Uid
        media->SetTObjectValueL<TUid>( 
        KMPXMediaGeneralCollectionId,
        Host().PlaylistCollectionId() );
        // Set type
        media->SetTObjectValueL<TMPXGeneralType>( 
        KMPXMediaGeneralType, EMPXItem );
        // Set category
        media->SetTObjectValueL<TMPXGeneralCategory>( 
        KMPXMediaGeneralCategory, EMPXPlaylist );
        // Set playlist ID
        media->SetTObjectValueL<TMPXItemId>(
        KMPXMediaGeneralId, KHostAppUid.iUid );
        // Add playlist into media object
        CMPXMediaArray* playlist = CMPXMediaArray::NewL();
        CleanupStack::PushL( playlist ); 
        iPlaylistActualSize += DoFillL( *playlist, array );
        media->SetCObjectValueL( 
        KMPXMediaArrayContents, playlist );
        // Add count of items in playlist
        media->SetTObjectValueL( 
        KMPXMediaArrayCount,
        playlist->Count() );
        CleanupStack::PopAndDestroy( playlist );

        __LOG( "CUPnPBrowsePlaylistFiller::AddMediaToCollectionL - \
        Collection->SetSyncL" );
        // Add new playlist to the collection
        Host().CollectionUtility().Collection().SetSyncL( *media );
        CleanupStack::PopAndDestroy( media );
        }
    else
        {
        __LOG( "CUPnPBrowsePlaylistFiller::AddMediaToCollectionL - \
        No items received!" );
        User::Leave( KErrNotFound );
        }
    array.ResetAndDestroy();
    CleanupStack::PopAndDestroy( parser );
    }

// --------------------------------------------------------------------------
// CUPnPBrowsePlaylistFiller::MediaServerDisappeared
// The media server has vanished
// --------------------------------------------------------------------------
//    
void CUPnPBrowsePlaylistFiller::MediaServerDisappeared( 
    TUPnPDeviceDisconnectedReason /*aReason*/ )
    {
    __LOG( "CUPnPBrowsePlaylistFiller::MediaServerDisappeared" );
    DoComplete();
    }

// --------------------------------------------------------------------------
// Unused callback methods from the interface
// --------------------------------------------------------------------------
//    
 
void CUPnPBrowsePlaylistFiller::SearchResponse( 
    const TDesC8& /*aSearchResponse*/, TInt /*aError*/, TInt /*aMatches*/,
    TInt /*aTotalCount*/, const TDesC8& /*aUpdateId*/ ) {}
void CUPnPBrowsePlaylistFiller::SearchCapabilitiesResponse( TInt /*aError*/,
    const TDesC8& /*aSearchCapabilities*/ ) {}
void CUPnPBrowsePlaylistFiller::CreateContainerResponse( TInt /*aError*/, 
    const TDesC8& /*aObjectId*/ ) {}
void CUPnPBrowsePlaylistFiller::DeleteObjectResponse( TInt /*aError*/ ) {}
void CUPnPBrowsePlaylistFiller::ReserveLocalMSServicesCompleted( TInt 
    /*aError*/ ) {}

// --------------------------------------------------------------------------
// CUPnPBrowsePlaylistFiller::HandlePeriod
// Action when timer has expired.
// --------------------------------------------------------------------------
// 
void CUPnPBrowsePlaylistFiller::HandlePeriod()
    {
    __LOG( "CUPnPBrowsePlaylistFiller::HandlePeriod" );

    TRAP_IGNORE( 
    // start a browsing session if not already started
    if( iBrowsingSession == 0 )
        {
        __LOG( "Start a browsing session" );
        iBrowsingSession = &Host().AVController()
            .StartBrowsingSessionL( SourceDevice() );
        iBrowsingSession->SetObserver( *this );
        }

    __LOG( "Start doing more browse requests" );
    // Start doing more browse requests
    iBrowsingSession->BrowseL( *iContainerId, KFilterMin,
        MUPnPAVBrowsingSession::EDirectChildren, iCurrentIndex,
        iBlocksize, KSortNone );
        );
    }