upnpavcontroller/upnpavcontrollerserver/src/upnpdevicerepository.cpp
author samhuttu
Mon, 01 Nov 2010 12:37:49 +0200
branchnew development branch with rendering state machine and other goodies
changeset 38 5360b7ddc251
parent 32 3785f754ee62
permissions -rw-r--r--
New development branch with e.g. rendering state machine and a simple Qt example application using it.

/*
* Copyright (c) 2005-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:      storage for devices with extended information
*
*/






// INCLUDE FILES
#include "upnpdevicerepository.h"

#include "upnpavdeviceextended.h"
#include "upnpavcontrolpoint.h"

#include <upnpservice.h>
#include <upnpdevice.h>
#include <upnpicon.h>
#include "upnpavcontrollerglobals.h"    // For KRel_Time

// CONSTANTS
_LIT8( KSearch,                     "Search" );
_LIT8( KVolume,                     "Volume" );
_LIT8( KCreateObject,               "CreateObject" );
_LIT8( KPause,                      "Pause");
_LIT8( KSetVolume,                  "SetVolume");
_LIT8( KGetVolume,                  "GetVolume");
_LIT8( KGetMute,                    "GetMute");
_LIT8( KSetMute,                    "SetMute");
_LIT8( KMediaServer,                "MediaServer" );
_LIT8( KFriendlyName,               "friendlyName" );
_LIT8( KModelName,                  "modelName" );
_LIT8( KAVTransportService,         "AVTransport" );
_LIT8( KRenderingControlService,    "RenderingControl" );
_LIT8( KSetNextUri,                 "SetNextAVTransportURI" );
_LIT8( KPrepareForConnection,       "PrepareForConnection" );
_LIT8( KDestroyObject,              "DestroyObject" );
_LIT8( KDlnaDoc,                    "dlna:X_DLNADOC" );
_LIT8( KDlnaCap,                    "dlna:X_DLNACAP" );
_LIT8( KAudioUpload,                "audio-upload" );
_LIT8( KImageUpload,                "image-upload" );
_LIT8( KVideoUpload,                "av-upload" );
_LIT8( KCreateChildContainer,       "create-child-container" );
_LIT8( KDMS,                        "DMS" );
_LIT8( KDMP,                        "DMP" );
_LIT8( KDMR,                        "DMR" );
_LIT8( KJpg,                        "jpg" );
_LIT8( KJpeg,                       "jpeg" );
_LIT8( KPng,                        "png" );
// Prefer 48x48 color icons and then greater size color icons
const TInt KPreferredIconSize = 48;

// Seek mode argument type string
_LIT8( KArgumentTypeSeekMode, "A_ARG_TYPE_SeekMode" );

const TInt KFirstSubscription = 1;

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

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

// --------------------------------------------------------------------------
// CUPnPDeviceRepository::NewL
// See upnpdevicerepository.h
// --------------------------------------------------------------------------
CUPnPDeviceRepository* CUPnPDeviceRepository::NewL
    (
    CUpnpAVControlPoint& aControlPoint
    )
    {
    CUPnPDeviceRepository* rep= new(ELeave)
        CUPnPDeviceRepository( aControlPoint );
    CleanupStack::PushL( rep );
    rep->ConstructL();
    CleanupStack::Pop();
    return rep;
    }

// --------------------------------------------------------------------------
// CUPnPDeviceRepository::~CUPnPDeviceRepository
// See upnpdevicerepository.h
// --------------------------------------------------------------------------
CUPnPDeviceRepository::~CUPnPDeviceRepository()
    {     
    iDevices.ResetAndDestroy();
    iDevices.Close();
    }
    
// --------------------------------------------------------------------------
// CUPnPDeviceRepository::CUPnPDeviceRepository
// See upnpdevicerepository.h
// --------------------------------------------------------------------------
CUPnPDeviceRepository::CUPnPDeviceRepository
    (
    CUpnpAVControlPoint& aControlPoint
    ):
    iControlPoint( aControlPoint ),
    iIsWlanActive( ETrue )    
    {
    }
    
// --------------------------------------------------------------------------
// CUPnPDeviceRepository::ConstructL
// See upnpdevicerepository.h
// --------------------------------------------------------------------------
void CUPnPDeviceRepository::ConstructL()
    {
    __LOG( "CUPnPDeviceRepository::ConstructL" );
    }

// --------------------------------------------------------------------------
// CUPnPDeviceRepository::AddDeviceL
// See upnpdevicerepository.h
// --------------------------------------------------------------------------
CUpnpAVDeviceExtended& CUPnPDeviceRepository::AddDeviceL( CUpnpDevice& aDevice )
    {
    __LOG( "CUPnPDeviceRepository::AddDeviceL" );
        
    CUpnpAVDeviceExtended* dev = CUpnpAVDeviceExtended::NewL();
    CleanupStack::PushL( dev );
    
    // Check if it's a dlna device
    TPtrC8 ptr = aDevice.GetProperty( KDlnaDoc );
    if( ptr.Length() > 0 )
        {
        __LOG( "Dlna compatible device!" );
        // It's a dlna device
        dev->SetDlnaCompatible( ETrue );
        
        if( ptr.FindC( KDMS ) != KErrNotFound )
            {
            dev->SetDLNADeviceType( CUpnpAVDeviceExtended::EDMS );
            }
        else if( ptr.FindC( KDMR ) != KErrNotFound )
            {
            dev->SetDLNADeviceType( CUpnpAVDeviceExtended::EDMR );
            }
        else if( ptr.FindC( KDMP ) != KErrNotFound )
            {
            dev->SetDLNADeviceType( CUpnpAVDeviceExtended::EDMP );
            }        
        
        // Check dlna capabilities
        ptr.Set( aDevice.GetProperty( KDlnaCap ) );
        if( ptr.Find( KAudioUpload ) != KErrNotFound )        
            {
            __LOG( "Audio upload supported!" );
            dev->SetAudioUpload( ETrue );
            }
        if( ptr.Find( KImageUpload ) != KErrNotFound )
            {
            __LOG( "Image upload supported!" );
            dev->SetImageUpload( ETrue );
            }
        if( ptr.Find( KVideoUpload ) != KErrNotFound )
            {
            __LOG( "Video upload supported!" );
            dev->SetVideoUpload( ETrue );
            }
        if( ptr.Find( KCreateChildContainer ) != KErrNotFound )
            {
            __LOG( "Create child container supported!" );
            dev->SetCreateChildContainer( ETrue );
            }        
        }   
        
    if( aDevice.DeviceType().Find( KMediaServer ) != KErrNotFound )
        {
        dev->SetDeviceType( CUpnpAVDevice::EMediaServer );
        }
    else
        {
        dev->SetDeviceType( CUpnpAVDevice::EMediaRenderer );
        }

    dev->SetFriendlyNameL( aDevice.DescriptionProperty( KFriendlyName ) );

    dev->SetModelNameL( aDevice.DescriptionProperty( KModelName ) );
    
    dev->SetUuidL( aDevice.Uuid() );   
    
    dev->SetLocal( aDevice.Local() );

    ParseDeviceServicesL( aDevice, *dev );

    SelectDeviceIconL( aDevice, *dev );

    CleanupStack::Pop( dev );
    iDevices.AppendL( dev );
    return *dev;
    }
    
// --------------------------------------------------------------------------
// CUPnPDeviceRepository::AddProtocolInfoL
// See upnpdevicerepository.h
// --------------------------------------------------------------------------
CUpnpAVDeviceExtended& CUPnPDeviceRepository::AddProtocolInfoL(
    const TDesC8& aUuid, const TDesC8& aSource, const TDesC8& aSink )
    {
    __LOG( "CUPnPDeviceRepository::AddProtocolInfoL" );
    
    // Find the device
    TInt count = iDevices.Count();
    CUpnpAVDeviceExtended* dev = NULL;
    for( TInt i = 0; i < count; i++ )
        {
        if( iDevices[ i ]->Uuid() == aUuid )
            {
            dev = iDevices[ i ];
            i = count;
            }
        }
    if( dev )
        {
        if( dev->DeviceType() == CUpnpAVDevice::EMediaServer )
            {
            dev->SetSourceProtocolInfoL( aSource );
            dev->SetSinkProtocolInfoL( aSink );
            dev->SetCapabilitiesBySupportedMimeTypesL( aSource );
            }
        else
            {
            dev->SetSourceProtocolInfoL( aSource );
            dev->SetSinkProtocolInfoL( aSink );
            dev->SetCapabilitiesBySupportedMimeTypesL( aSink );    
            }
        dev->SetPInfoReceived( ETrue );        
        }
    else
        {
        User::Leave( KErrNotFound );
        }    
    return *dev;
    }

// --------------------------------------------------------------------------
// CUPnPDeviceRepository::Remove
// See upnpdevicerepository.h
// --------------------------------------------------------------------------
void CUPnPDeviceRepository::Remove( const TDesC8& aUuid )
    {
    __LOG( "CUPnPDeviceRepository::Remove" );
    
    TInt count = iDevices.Count();
    for( TInt i = 0; i < count; i++ )
        {
        if( iDevices[ i ]->Uuid() == aUuid )
            {
            delete iDevices[ i ];
            iDevices.Remove( i );
            i = count;
            }
        }
    
    }

// --------------------------------------------------------------------------
// CUPnPDeviceRepository::FindDeviceL
// See upnpdevicerepository.h
// --------------------------------------------------------------------------
CUpnpAVDeviceExtended& CUPnPDeviceRepository::FindDeviceL(
    const TDesC8& aUuid )
    {
    __LOG( "CUPnPDeviceRepository::FindDeviceL" );
    
    CUpnpAVDeviceExtended* tmp = NULL;
    TInt count = iDevices.Count();
    for( TInt i = 0; i < count; i++ )
        {
        if( iDevices[ i ]->Uuid() == aUuid )
            {
            tmp = iDevices[ i ];
            i = count;
            }
        }
    if( !tmp )
        {
        __LOG( "FindDeviceL - not found" );
        
        User::Leave( KErrNotFound );
        }
    return *tmp;    
    }

// --------------------------------------------------------------------------
// CUPnPDeviceRepository::DeviceList
// See upnpdevicerepository.h
// --------------------------------------------------------------------------
const RPointerArray<CUpnpAVDeviceExtended>&
    CUPnPDeviceRepository::DeviceList() const
    {
    __LOG( "CUPnPDeviceRepository::DeviceList" );
    
    return iDevices;
    }
   
// --------------------------------------------------------------------------
// CUPnPDeviceRepository::SubscribeDeviceL
// See upnpdevicerepository.h
// --------------------------------------------------------------------------
void CUPnPDeviceRepository::SubscribeDeviceL( const TDesC8& aUuid )
    {
    __LOG( "CUPnPDeviceRepository::SubscribeDeviceL" );
    __LOG8( aUuid );
    
    // Find the device and increase subscription count/check if we have
    // subscribed already
    TInt count = iDevices.Count();
    TInt subscriptionCount = KErrNotFound;
    TInt index;
    for( index = 0; index < count; index++ )
        {
        if( aUuid.Compare( iDevices[ index ]->Uuid() ) == 0 )
            {
            subscriptionCount = iDevices[ index ]->IncreaseSubscriptionCount();
            index = count;
            }
        }
    if( subscriptionCount == KFirstSubscription )
        {
        __LOG( "SubscribeDeviceL - First subscription" ); 
        
        // Start subsciption for AVTransport and RenderingControl services
        // Find the device
        const RPointerArray<CUpnpDevice>& devList =
            iControlPoint.DeviceList();
        count = devList.Count();
        for( index = 0; index < count; index++ )
            {
            if( aUuid.Compare( devList[ index ]->Uuid() ) == 0 )
                {
                break;
                }
            }

        // Find the AVTransport service and subscribe
        RPointerArray<CUpnpService>& servList =
            devList[ index ]->ServiceList();
        count = servList.Count();
        CUpnpService* tempService = NULL;
        for( index = 0; index < count; index++ )
            {
            if( servList[ index ]->ServiceType().Find(
                KAVTransportService ) >= 0 )
                {
                tempService = servList[ index ];
                index = count;
                }
            }
        if( tempService && iIsWlanActive )
            {
            // AVTransport service found for the device, subscribe
            __LOG( "SubscribeDeviceL - Subscribe for AVTransport" ); 
            iControlPoint.SubscribeL( tempService ); 
            }
        else
            {     
            // Service not found, can't subscribe
            __LOG( "SubscribeDeviceL - AVTransport service not found" );
            }
            
        tempService = NULL;
        for( index = 0; index < count; index++ )
            {
            if( servList[ index ]->ServiceType().Find(
                KRenderingControlService ) >= 0 )
                {
                tempService = servList[ index ];
                index = count;
                }
            }
        if( tempService && iIsWlanActive )
            {
            // RenderingControl service found for the device, subscribe
            __LOG( "SubscribeDeviceL - Subscribe for RenderingControl" ); 
            iControlPoint.SubscribeL( tempService ); 
            }
        else
            {     
            // Service not found, can't subscribe
            __LOG( "SubscribeDeviceL - RenderingControl service not found" );
            }                    
        }
    else if( subscriptionCount == KErrNotFound ) 
        {
        __LOG( "SubscribeDeviceL - device not found" );
        }
    else
        {
        // Subscribed already, do nothing
        __LOG( "SubscribeDeviceL - Subscription done already, ignoring!" ); 
        }        
    }
    
// --------------------------------------------------------------------------
// CUPnPDeviceRepository::UnSubscribeDeviceL
// See upnpdevicerepository.h
// --------------------------------------------------------------------------
void CUPnPDeviceRepository::UnSubscribeDeviceL( const TDesC8& aUuid )
    {
    __LOG( "CUPnPDeviceRepository::UnSubscribeDeviceL" );
    __LOG8( aUuid );
    
    // Find the device and decrease subscription count/check if it's needed
    // to unsubscribe
    TInt count = iDevices.Count();
    TInt subscriptionCount = KErrNotFound;
    TInt index;
    for( index = 0; index < count; index++ )
        {
        if( aUuid.Compare( iDevices[ index ]->Uuid() ) == 0 )
            {
            subscriptionCount = 
                iDevices[ index ]->DecreaseSubscriptionCount();
            index = count;
            }
        }    
    
    if( subscriptionCount == 0 )
        {   
        // Start unsubsciption for AVTransport and RenderingControl services
        // Find the device
        const RPointerArray<CUpnpDevice>& devList =
            iControlPoint.DeviceList();
        count = devList.Count();
        for( index = 0; index < count; index++ )
            {
            if( aUuid.Compare( devList[ index ]->Uuid() ) == 0 )
                {
                break;
                }
            }

        // Find the AVTransport service and unsubscribe
        RPointerArray<CUpnpService>& servList =
            devList[ index ]->ServiceList();
        count = servList.Count();
        CUpnpService* tempService = NULL;
        for( index = 0; index < count; index++ )
            {
            if( servList[ index ]->ServiceType().Find(
                KAVTransportService ) >= 0 )
                {
                tempService = servList[ index ];
                index = count;
                }
            }
        if( tempService && iIsWlanActive )
            {
            // AVTransport service found for the device, unsubscribe
            __LOG( "UnSubscribeDeviceL - UnSubscribe AVTransport" ); 
            iControlPoint.UnsubscribeL( tempService ); 
            }
        else
            {     
            // Service not found, can't unsubscribe
            __LOG( "UnSubscribeDeviceL - AVTransport service not found" );
            }
            
        tempService = NULL;
        for( index = 0; index < count; index++ )
            {
            if( servList[ index ]->ServiceType().Find(
                KRenderingControlService ) >= 0 )
                {
                tempService = servList[ index ];
                index = count;
                }
            }
        if( tempService && iIsWlanActive )
            {
            // RenderingControl service found for the device, subscribe
            __LOG( "UnSubscribeDeviceL - UnSubscribe RenderingControl" ); 
            iControlPoint.UnsubscribeL( tempService ); 
            }
        else
            {     
            // Service not found, can't subscribe
            __LOG( "UnSubscribeDeviceL - RenderingControl service not\
found" );
            }                    
        }
    else if( subscriptionCount == KErrNotFound ) 
        {
        __LOG( "UnSubscribeDeviceL - device not found" );
        }
    else
        {
        // No need to unsubscibe
        }           
    }

// --------------------------------------------------------------------------
// CUPnPDeviceRepository::ConnectionLost
// See upnpdevicerepository.h
// --------------------------------------------------------------------------
void CUPnPDeviceRepository::ConnectionLost()
    {
    __LOG( "CUPnPDeviceRepository::ConnectionLost" );
    iIsWlanActive = EFalse;
    iDevices.ResetAndDestroy();
    }

// --------------------------------------------------------------------------
// CUPnPDeviceRepository::IsWlanActive
// See upnpdevicerepository.h
// --------------------------------------------------------------------------
TBool CUPnPDeviceRepository::IsWlanActive()
    {
    __LOG1( "CUPnPDeviceRepository::IsWlanActive, %d", (TInt)iIsWlanActive );
    return iIsWlanActive;
    }

// --------------------------------------------------------------------------
// CUPnPDeviceRepository::SetMaxVolume
// See upnpdevicerepository.h
// --------------------------------------------------------------------------
void CUPnPDeviceRepository::SetMaxVolume(CUpnpStateVariable* aVolumeState,
        CUpnpAVDeviceExtended& aTarget)
    {
    if( aVolumeState )
        {
        // If volume info found, save it to the device
        TInt maxVolume = aVolumeState->MaxValue();
        // If max volume not defined, it is set to 100
        if( maxVolume == KErrNotFound )
            {
            maxVolume = 100;
            }
        aTarget.SetMaxVolume( maxVolume );
        }
    }

// --------------------------------------------------------------------------
// CUPnPDeviceRepository::SetSeekCapabilityL
// See upnpdevicerepository.h
// --------------------------------------------------------------------------
void CUPnPDeviceRepository::SetSeekCapabilityL(CUpnpStateVariable* seekModeStateVariable,
        CUpnpAVDeviceExtended& aTarget)
    {
    if ( seekModeStateVariable ) 
        {
        CDesC8Array* allowedSeekModes = 
            seekModeStateVariable->AllowedValuesLC();
        if ( allowedSeekModes ) 
            {
            for ( TInt i=0 ; i < allowedSeekModes->Count() ; i++ ) 
                {
                if ( 0 == allowedSeekModes->
                            operator[](i).CompareC( KRel_Time() ) )
                    {
                    aTarget.SetSeekCapability( CUpnpAVDevice::ERelTime );
                    break;
                    }
                }               
            }
        CleanupStack::PopAndDestroy( allowedSeekModes );
        }
    }

// --------------------------------------------------------------------------
// CUPnPDeviceRepository::ParseDeviceServicesL
// See upnpdevicerepository.h
// --------------------------------------------------------------------------
void CUPnPDeviceRepository::ParseDeviceServicesL( CUpnpDevice& aSource,
    CUpnpAVDeviceExtended& aTarget )
    {
    __LOG( "CUPnPDeviceRepository::ParseDeviceServicesL" );
    
    TBool createObjectSupported = EFalse;
    TBool getMuteSupported = EFalse;
    TBool setMuteSupported = EFalse;
    TBool getVolumeSupported = EFalse;
    TBool setVolumeSupported = EFalse;

    RPointerArray<CUpnpService>& services = aSource.ServiceList();

    TInt i;
    TInt count = services.Count(); 
    for( i = 0; i < count; i++ )
        {
       CUpnpStateVariable* volumeState = 
                services[ i ]->StateVariable( KVolume );

       SetMaxVolume(volumeState, aTarget);

        CUpnpStateVariable* seekModeStateVariable = 
            services[i]->StateVariable( KArgumentTypeSeekMode() );
        
        SetSeekCapabilityL(seekModeStateVariable, aTarget);

        // Get the actions
        RPointerArray<CUpnpAction> actions;
        // 'actions' cannot be closed, it is the same instance that is inside 'service'
        services[ i ]->GetActionList( actions );

        // Go through the action elements
        TInt j;
        TInt count2 = actions.Count();
        for( j = 0; j < count2; j++ )
            {
            TDesC8& actionName = actions[ j ]->Name();

            if( actionName != KNullDesC8 )
                {
                if( actionName.Find( KCreateObject ) >= 0 )
                    {
                    createObjectSupported = ETrue;
                    }
                if( actionName.Compare( KSearch ) == 0 )
                    {
                    aTarget.SetSearchCapability( ETrue );
                    }
                if( actionName.Find( KPause ) >= 0 )
                    {
                    aTarget.SetPauseCapability( ETrue );
                    }
                if( actionName.Find( KGetVolume ) >= 0 )
                    {
                    getVolumeSupported = ETrue;
                    }
                if( actionName.Find( KSetVolume ) >= 0 )
                    {
                    setVolumeSupported = ETrue;
                    }
                if( actionName.Find( KGetMute ) >= 0 )
                    {
                    getMuteSupported = ETrue;
                    }
                if( actionName.Find( KSetMute ) >= 0 )
                    {
                    setMuteSupported = ETrue;
                    }
                if( actionName.Find( KSetNextUri ) >= 0 )
                    {
                    aTarget.SetNextAVTransportUri( ETrue );
                    }
                if( actionName.Find( KDestroyObject ) >= 0 )
                    {
                    aTarget.SetDestroyObject( ETrue );
                    }
                if( actionName.Find( KPrepareForConnection ) >= 0 )
                    {
                    aTarget.SetPrepareForConnection( ETrue );
                    }
                }
            }
        }

    // Set copy support
    if( createObjectSupported )
        {
        aTarget.SetCopyCapability( ETrue );
        }

    // Set volume support
    if( getVolumeSupported &&
        setVolumeSupported )
        {
        aTarget.SetVolumeCapability( ETrue );
        }

    // Set mute support
    if( getMuteSupported &&
        setMuteSupported )
        {
        aTarget.SetMuteCapability( ETrue );
        }
        
     }

// --------------------------------------------------------------------------
// CUPnPDeviceRepository::SelectDeviceIconL
// See upnpdevicerepository.h
// --------------------------------------------------------------------------
void CUPnPDeviceRepository::SelectDeviceIconL( CUpnpDevice& aSource,
    CUpnpAVDeviceExtended& aTarget )
    {
    // Icon selection rules:
    // 1. Select any if none selected
    // 2. Select the most colorful
    // 3. Select greater until preferred size reached
    // 4. Select the closest greater size after preferred size has passed
    TPtrC8 deviceName( aTarget.FriendlyName() );
    __LOG8_1( "CUPnPDeviceRepository::SelectDeviceIconL - Device: %S", &deviceName );
    RPointerArray< CUpnpIcon >& icons( aSource.Icons() );
    TInt iconCount( icons.Count() );
    CUpnpIcon* selectedIcon = NULL;
    TInt selectedDepth( 0 );
    TInt selectedWd( 0 );
    TInt selectedHd( 0 );
    TInt selectedWhdSquare( 0 );
    for ( TInt i( 0 ); i < iconCount; ++i )
        {
        CUpnpIcon* icon = icons[ i ];
        TPtrC8 iconMimeType( icon->MimeType() );
        __LOG8_1( "CUPnPDeviceRepository::SelectDeviceIconL - Found: %S", &iconMimeType );
        __LOG3( "CUPnPDeviceRepository::SelectDeviceIconL - Width: %d Height: %d Depth: %d",
                icon->Width(), icon->Height(), icon->Depth() );
        if ( iconMimeType.FindF( KJpg ) != KErrNotFound ||
             iconMimeType.FindF( KJpeg ) != KErrNotFound ||
             iconMimeType.FindF( KPng ) != KErrNotFound )
            {
            TInt depth( icon->Depth() );
            TInt wd( icon->Width() - KPreferredIconSize ); // Width diff to preferred size
            TInt hd( icon->Height() - KPreferredIconSize ); // Height diff to preferred size
            TInt whdSquare( wd * wd + hd * hd ); // Diffs combined
            if ( !selectedIcon || // Rule 1
                 ( depth >= selectedDepth && // Rule 2
                   ( ( selectedWd < 0 && selectedWd < 0 && ( wd > selectedWd || hd > selectedHd ) ) || // Rule 3
                     ( whdSquare < selectedWhdSquare && ( wd >= 0 || hd >= 0 ) ) ) // Rule 4
                   )
                 )
                {
                selectedIcon = icon;
                selectedDepth = depth;
                selectedWd = wd;
                selectedHd = hd;
                selectedWhdSquare = whdSquare;
                }
            }
        }
    if ( selectedIcon )
        {
        TPtrC8 iconMimeType( selectedIcon->MimeType() );
        __LOG8_1( "CUPnPDeviceRepository::SelectDeviceIconL - Selected: %S", &iconMimeType );
        __LOG3( "CUPnPDeviceRepository::SelectDeviceIconL - Width: %d Height: %d Depth: %d",
                selectedIcon->Width(), selectedIcon->Height(), selectedIcon->Depth() );
        aTarget.SetIconUrlL( aSource.Address(), aSource.UrlBase(), selectedIcon->Url() );
        }
    else
        {
        __LOG( "CUPnPDeviceRepository::SelectDeviceIconL - None selected" );
        }
    }

// end of file