upnpavcontroller/upnpavcontrollerserver/src/upnpdownloadsession.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) 2008 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:      server impl. of session against media server
*
*/






// INCLUDE FILES
// System
#include <f32file.h>

// upnp stack api
#include <upnpstring.h>

// dlnasrv / mediaserver api
#include <upnpmediaserversettings.h>
#include <upnpdlnaprotocolinfo.h>
#include <upnpdlnaprotocolinfocons.h>

// dlnasrv / avcontroller helper api
#include "upnpconstantdefs.h" // for upnp-specific stuff

// dlnasrv / internal api's
#include "upnpcommonutils.h"
#include "httpdownloader.h"

// dlnasrv / avcontroller internal
#include "upnpdownloadsession.h"
#include "upnpavdeviceextended.h"
#include "upnpfiletransferitem.h"
#include "upnpavcontrollerserver.h"
#include "upnpaverrorhandler.h"

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

// CONSTANTS
const TUint32 KBufferSize       = 0x40000; // 256K
const TInt KParallerTransfers   = 1;

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

// --------------------------------------------------------------------------
// CUPnPDownloadSession::NewL
// See upnpdownloadsession.h
// --------------------------------------------------------------------------
CUPnPDownloadSession* CUPnPDownloadSession::NewL( CUpnpAVControllerServer&
    aServer, TInt aSessionId, const TDesC8& aUuid )
    {
    __LOG( "CUPnPDownloadSession::NewL" );
    
    CUPnPDownloadSession* self = new (ELeave) CUPnPDownloadSession(
        aServer, aSessionId );
    CleanupStack::PushL( self );    
    self->ConstructL( aUuid );
    CleanupStack::Pop( self );
    return self;
    }

// --------------------------------------------------------------------------
// CUPnPDownloadSession::CUPnPDownloadSession
// See upnpdownloadsession.h
// --------------------------------------------------------------------------
CUPnPDownloadSession::CUPnPDownloadSession( CUpnpAVControllerServer&
    aServer, TInt aSessionId ) :
    CUPnPFileTransferSessionBase( aServer, aSessionId )
    {
    __LOG( "CUPnPDownloadSession::CUPnPDownloadSession" );
    
    }

// --------------------------------------------------------------------------
// CUPnPDownloadSession::~CUPnPDownloadSession
// See upnpdownloadsession.h
// --------------------------------------------------------------------------
CUPnPDownloadSession::~CUPnPDownloadSession()
    {
    __LOG( "CUPnPDownloadSession::~CUPnPDownloadSession" );
    
    delete iDownloader;
    
    __LOG( "CUPnPDownloadSession::~CUPnPDownloadSession - end" );
    }

// --------------------------------------------------------------------------
// CUPnPDownloadSession::ConstructL
// See upnpdownloadsession.h
// --------------------------------------------------------------------------
void CUPnPDownloadSession::ConstructL( const TDesC8& aUuid )
    {
    __LOG( "CUPnPDownloadSession::ConstructL" );
    
    CUPnPFileTransferSessionBase::ConstructL( aUuid );

    iDownloader = CHttpDownloader::NewL( *this, (TUint32)iServer.IAP(),
        KBufferSize, KParallerTransfers );
    }
   
// --------------------------------------------------------------------------
// CUPnPDownloadSession::TransferProgress
// See upnpdownloadsession.h
// --------------------------------------------------------------------------
void CUPnPDownloadSession::TransferProgress( TAny* aKey, TInt aBytes,
    TInt aTotalBytes )
    {
    __LOG( "CUPnPDownloadSession::TransferProgress" );
    
    if( iProgressTrackingEnabled )
        {
        TUpnpFileTransferEvent item;
        TInt err = FindItemByKey( item, (TInt)aKey );
        if( err == KErrNone )
            {
            item.iStatus = KErrNone;
            item.iParam2 = aTotalBytes;
            item.iParam1 = aBytes;
            item.iEvent = TUpnpFileTransferEvent::ETransferProgress;

            Complete( item );                            
            }
        else
            {
            __LOG( "TransferProgress - Not enabled!" );
            }
        }
    }

// --------------------------------------------------------------------------
// CUPnPDownloadSession::ReadyForTransfer
// See upnpdownloadsession.h
// --------------------------------------------------------------------------
void CUPnPDownloadSession::ReadyForTransferL( TAny* aKey )
    {
    __LOG( "CUPnPDownloadSession::ReadyForTransfer" );

    TUpnpFileTransferEvent item;
    TInt err = FindItemByKey( item, (TInt)aKey );
    if( err == KErrNone )
        {       
        iDownloader->StartTransferL( aKey );        
    
        item.iEvent = TUpnpFileTransferEvent::ETransferStarted;
        Complete( item );
        }
    else
        {
        __LOG( "ReadyForTransfer - key not found" );

        // Not found
        item.iStatus = KErrGeneral;
        item.iParam2 = 0;
        item.iEvent = TUpnpFileTransferEvent::ETransferCompleted;
        
        Complete( item );
        }
    }

// --------------------------------------------------------------------------
// CUPnPDownloadSession::TransferCompleted
// See upnpdownloadsession.h
// --------------------------------------------------------------------------
void CUPnPDownloadSession::TransferCompleted( TAny* aKey, TInt aStatus )
    {
    __LOG( "CUPnPDownloadSession::TransferCompleted" );
    
    TUpnpFileTransferEvent item;
    TInt index;
    TInt err = FindItemByKey( item, (TInt)aKey, index );
    if( err == KErrNone )
        {
        item.iStatus = UPnPAVErrorHandler::ConvertToSymbianErrorCode( 
                aStatus,
                EUPnPHTTPError );
        item.iEvent = TUpnpFileTransferEvent::ETransferCompleted;
        item.iParam3 = 0;

        const HBufC* path = NULL;
        TRAPD( err, path = iDownloader->GetPropertyL( aKey,
            CHttpTransferBase::ETargetPath ) );

        if( iEventMsg )
            {
            if( err == KErrNone && path )
                {
                // Write path using slot 2
                iEventMsg->Write( 2, *path );                            
                }
            else
                {
                __LOG( "Error in path handling" );
                }    
            }
        else
            {
            if( err == KErrNone && path )
                {
                HBufC* buf = HBufC::New( path->Length() );
                if( buf )
                    {
                    buf->Des().Copy( *path );
                    item.iParam3 = (TAny*)buf;
                    }
                else
                    {
                    __LOG( "Error in path handling" );
                    }    
                }
            }    
        Complete( item );
        
        iTransferItems.Remove( index );      
        }
    else
        {
        // Corresponding key was not found!
        __LOG( "TransferCompleted - key not found" );

        // Not found
        item.iStatus = KErrGeneral;
        item.iParam2 = 0;
        item.iEvent = TUpnpFileTransferEvent::ETransferCompleted;
        
        Complete( item );        
        }
        
    if( aStatus == KErrDisconnected )
        {
        __LOG( "TransferCompleted - Target device lost" );
        
        TInt count = iTransferItems.Count();
        for( TInt i = 0; i < count; i++ )
            {
            iDownloader->CancelTransfer( (TAny*)iTransferItems[i].iKey );
            }
        iTransferItems.Reset();
        iEventQueu.Reset();            
        }
    }

// --------------------------------------------------------------------------
// CUPnPDownloadSession::StartDownloadL
// See upnpdownloadsession.h
// --------------------------------------------------------------------------
void CUPnPDownloadSession::StartDownloadL( const RMessage2& aMessage )
    {
    __LOG( "CUPnPDownloadSession::StartDownloadL" );
    
    CUpnpFileTransferItem* tmpTransferItem = CUpnpFileTransferItem::NewLC();
        
    ReadTransferItemFromMessageL( aMessage, 1 ,tmpTransferItem );
        
    TUpnpFileTransferEvent transferItem;
    
    if( CheckIfKeyExists( tmpTransferItem->Key() ) )
        {
        User::Leave( KErrInUse );
        }
        
    transferItem.iKey = tmpTransferItem->Key();
    
    HBufC* path = HBufC::NewLC( KMaxPath );
    if( tmpTransferItem->Path() == KNullDesC )
        {
        // Read path from the settings
        CUpnpMediaServerSettings* msSettings =
            CUpnpMediaServerSettings::NewL();
        CleanupStack::PushL( msSettings );
               
        HBufC8* buf = msSettings->GetL(
            UpnpMediaServerSettings::EUploadDirectory );
            
        CleanupStack::PopAndDestroy( msSettings );    
        
        path->Des().Copy( *buf );
        delete buf;
        }
    else
        {
        // Get path from the transfer item
        path->Des().Copy( tmpTransferItem->Path() );
        }    
    
    __LOG8( tmpTransferItem->Title() );
    
    HBufC* title16 = UpnpString::ToUnicodeL( tmpTransferItem->Title() );
    CleanupStack::PushL( title16 );
    
    HBufC* title16checked =
        UPnPCommonUtils::ReplaceIllegalFilenameCharactersL( *title16 );
    CleanupStack::PopAndDestroy( title16 );
    CleanupStack::PushL( title16checked );
    
    CUpnpDlnaProtocolInfo* tmpInfo = CUpnpDlnaProtocolInfo::NewL(
        tmpTransferItem->ProtocolInfo() );
    CleanupStack::PushL( tmpInfo );    
    HBufC* fileExt = UPnPCommonUtils::FileExtensionByMimeTypeL(
        tmpInfo->ThirdField() );  
    path->Des().Append( *title16checked  );
    
    if( fileExt )
        {
        path->Des().Append( *fileExt );
        delete fileExt;        
        }

    iDownloader->InsertFileIntoWaitQueueL( (TAny*)transferItem.iKey,
        *path, tmpTransferItem->Uri() );
        
    SetHeadersL( *tmpInfo, (TAny*)transferItem.iKey );    
    CleanupStack::PopAndDestroy( tmpInfo );    
    CleanupStack::PopAndDestroy( title16checked );
    
    iTransferItems.Append( transferItem );
           
    iDownloader->MoveToTransferQueueL( (TAny*)transferItem.iKey );
    
    CleanupStack::PopAndDestroy( path );
    
    CleanupStack::PopAndDestroy( tmpTransferItem );
    
    aMessage.Complete( KErrNone );        
    }

// --------------------------------------------------------------------------
// CUPnPDownloadSession::StartDownloadFHL
// See upnpdownloadsession.h
// --------------------------------------------------------------------------
void CUPnPDownloadSession::StartDownloadFHL( const RMessage2& aMessage )
    {
    __LOG( "CUPnPDownloadSession::StartDownloadFHL" );

    RFile fHandle;
    // handle is stored in slots 2 and 3
    User::LeaveIfError( fHandle.AdoptFromClient( aMessage, 2, 3 ) );
    CleanupClosePushL( fHandle );
    
    CUpnpFileTransferItem* tmpTransferItem = CUpnpFileTransferItem::NewLC();
        
    ReadTransferItemFromMessageL( aMessage, 1 ,tmpTransferItem );
        
    TUpnpFileTransferEvent transferItem;
    transferItem.iKey = tmpTransferItem->Key();
    
    if( CheckIfKeyExists( tmpTransferItem->Key() ) )
        {
        User::Leave( KErrInUse );
        }
    
    CUpnpDlnaProtocolInfo* tmpInfo = CUpnpDlnaProtocolInfo::NewL(
        tmpTransferItem->ProtocolInfo() );
    CleanupStack::PushL( tmpInfo );     
    
    iDownloader->InsertFileIntoWaitQueueL( (TAny*)transferItem.iKey, fHandle,
        tmpTransferItem->Uri() );
    
    SetHeadersL( *tmpInfo, (TAny*)transferItem.iKey );
    
    CleanupStack::PopAndDestroy( tmpInfo );
        
    iTransferItems.Append( transferItem );

    iDownloader->MoveToTransferQueueL( (TAny*)transferItem.iKey );
        
    CleanupStack::PopAndDestroy( tmpTransferItem );
    
    CleanupStack::PopAndDestroy( &fHandle );
    
    aMessage.Complete( KErrNone );  
    }
    
// --------------------------------------------------------------------------
// CUPnPDownloadSession::CancelDownloadL
// See upnpdownloadsession.h
// --------------------------------------------------------------------------
void CUPnPDownloadSession::CancelDownloadL( const RMessage2& aMessage )
    {
    __LOG( "CUPnPDownloadSession::CancelDownloadL" );
    
    TInt key = aMessage.Int1();

    TInt index;
    if( CheckIfKeyExists( key, index ) )
        {
        iDownloader->CancelTransfer( (TAny*)key );
        aMessage.Complete( KErrNone );
        iTransferItems.Remove( index );
        }
    else
        {
        aMessage.Complete( KErrNotFound );
        }    
    
    }

// --------------------------------------------------------------------------
// CUPnPDownloadSession::CancelAllDownloadsL
// See upnpdownloadsession.h
// --------------------------------------------------------------------------
void CUPnPDownloadSession::CancelAllDownloadsL( const RMessage2& aMessage )
    {
    __LOG( "CUPnPDownloadSession::CancelAllDownloadsL" );
    
    TInt count = iTransferItems.Count();
    for( TInt i = 0; i < count; i++ )
        {
        iDownloader->CancelTransfer( (TAny*)iTransferItems[i].iKey );
        }
    iTransferItems.Reset();
    iEventQueu.Reset();    
    aMessage.Complete( KErrNone );
    }
    
// --------------------------------------------------------------------------
// CUPnPDownloadSession::StartTrackingDownloadProgressL
// See upnpdownloadsession.h
// --------------------------------------------------------------------------
void CUPnPDownloadSession::StartTrackingDownloadProgressL(
    const RMessage2& aMessage )
    {
    __LOG( "CUPnPDownloadSession::StartTrackingDownloadProgressL" );
    
    TInt key = aMessage.Int1();
    if( CheckIfKeyExists( key ) )
        {
        iDownloader->TrackProgress( (TAny*)key, ETrue );
        iProgressTrackingEnabled = ETrue;        
        aMessage.Complete( KErrNone );
        }
    else
        {
        aMessage.Complete( KErrNotFound );
        }    
    }
    
// --------------------------------------------------------------------------
// CUPnPDownloadSession::StopTrackingDownloadProgressL
// See upnpdownloadsession.h
// --------------------------------------------------------------------------
void CUPnPDownloadSession::StopTrackingDownloadProgressL(
    const RMessage2& aMessage )
    {
    __LOG( "CUPnPDownloadSession::StopTrackingDownloadProgressL" );
    
    TInt key = aMessage.Int1();
    if( CheckIfKeyExists( key ) )
        {
        iDownloader->TrackProgress( (TAny*)key, EFalse );
        iProgressTrackingEnabled = EFalse;        
        aMessage.Complete( KErrNone );
        }
    else
        {
        aMessage.Complete( KErrNotFound );
        }    
    }

// --------------------------------------------------------------------------
// CUPnPDownloadSession::GetDownloadEventL
// See upnpdownloadsession.h
// --------------------------------------------------------------------------
void CUPnPDownloadSession::GetDownloadEventL( const RMessage2& aMessage )
    {
    __LOG( "CUPnPDownloadSession::GetDownloadEventL" );
    
    if( iEventQueu.Count() )
        {
        __LOG1( "GetDownloadEventL, events in queu: %d",
            iEventQueu.Count() );
        
        // There are events in the queu, write the first queued event back
        // to client
        TUpnpFileTransferEvent event = iEventQueu[0];
        iEventQueu.Remove( 0 );
        TPckg<TUpnpFileTransferEvent> resp1( event );
        
        if( event.iEvent ==
            TUpnpFileTransferEvent::ETransferCompleted &&
            event.iParam3 )
            {
            // Write path using slot 2
            __LOG16( *( (HBufC*)event.iParam3 ) );
            aMessage.Write( 2, *( (HBufC*)event.iParam3 ) );
            delete (HBufC*)event.iParam3;
            }
        aMessage.Write( 1, resp1  ); // Write event using slot 1    
        aMessage.Complete( KErrNone );       
        }
    else
        {
        iEventMsg = new (ELeave) RMessage2( aMessage );    
        }
    __LOG( "CUPnPDownloadSession::GetDownloadEventL - end" );        
    }
    
// --------------------------------------------------------------------------
// CUPnPDownloadSession::CancelGetDownloadEventL
// See upnpdownloadsession.h
// --------------------------------------------------------------------------
void CUPnPDownloadSession::CancelGetDownloadEventL(
    const RMessage2& aMessage )
    {
    __LOG( "CUPnPDownloadSession::CancelGetDownloadEventL" );
    
    if( iEventMsg )
        {
        iEventMsg->Complete( KErrCancel );
        delete iEventMsg; iEventMsg = NULL;
        }
    aMessage.Complete( KErrNone );
    }

void CUPnPDownloadSession::DeviceDisappearedL(
    CUpnpAVDeviceExtended& aDevice )
    {
    __LOG( "CUPnPDownloadSession::DeviceDisappearedL" );
    
    if( aDevice.Uuid().Compare( iDevice->Uuid() ) == 0 )
        {
        TUpnpFileTransferEvent event;
        event.iEvent = TUpnpFileTransferEvent::EDeviceDisconnected;
        
        Complete( event );
        }
    }

// --------------------------------------------------------------------------
// CUPnPDownloadSession::SetHeadersL
// See upnpdownloadsession.h
// --------------------------------------------------------------------------
void CUPnPDownloadSession::SetHeadersL( CUpnpDlnaProtocolInfo& aInfo,
    TAny* aKey )
    {
    __LOG( "CUPnPDownloadSession::SetHeadersL" );
    
    // Check supported transfermodes
    // We MUST use background, if it's supported
    if( aInfo.DlnaFlag( UpnpDlnaProtocolInfo::TM_B_FLAG ) )
        {
        iDownloader->SetHeaderL( aKey, KTransferMode, KBackgroundMode );
        }
    else if( aInfo.DlnaFlag( UpnpDlnaProtocolInfo::TM_S_FLAG ) )
        {
        iDownloader->SetHeaderL( aKey, KTransferMode, KStreamingMode );
        }
    else if( aInfo.DlnaFlag( UpnpDlnaProtocolInfo::TM_I_FLAG ) )
        { 
        iDownloader->SetHeaderL( aKey, KTransferMode, KInteractiveMode );
        }      
    else 
        {
        __LOG( "SetHeadersL - No DLNA flags" );
        
        // Transfermode is not defined by any flag
        // Correction for HALA-7B6FA5
        if( UPnPCommonUtils::IsImageSupported( aInfo.ProtocolInfoL() ) )
            {
            __LOG( "SetHeadersL - Image -> Interactive" );
            // It's an image, we should use Interactive-mode
            iDownloader->SetHeaderL( aKey, KTransferMode, KInteractiveMode );
            }
        else if(
            UPnPCommonUtils::IsAudioSupported( aInfo.ProtocolInfoL() ) ||
            UPnPCommonUtils::IsVideoSupported( aInfo.ProtocolInfoL() ) )
            {
            __LOG( "SetHeadersL - A/V -> Streaming" );
            iDownloader->SetHeaderL( aKey, KTransferMode, KStreamingMode );
            }
        else
            {
            __LOG( "SetHeadersL - Unknown type -> No mode" );
            // It' something other
            }                    
        }        
    }
   
// End of file