upnpmpxplugins/upnpplaybackplugins/src/upnptrack.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Fri, 17 Sep 2010 08:31:21 +0300
changeset 32 3785f754ee62
parent 0 7f85d04be362
permissions -rw-r--r--
Revision: 201035 Kit: 201037

/*
* 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:      Class for containing and obtaining music track-specific data
*                from media server
*
*/






// INCLUDES
#include <mpxmediaaudiodefs.h>
#include <mpxmediamusicdefs.h>
#include <mpxmediageneraldefs.h>
#include <mpxmedia.h>
#include <mpxattribute.h>
#include <mpxplaybackpluginobserver.h>
#include <mpxmessagegeneraldefs.h> // for messaging
#include <mpxplaybackmessagedefs.h> // for messaging

#include <escapeutils.h> // for unicode conversion

#include <upnpitem.h>
#include <upnpobject.h>
#include "upnpitemutility.h" // for FindElementByName & ResourceFromItemL
#include "upnpfileutility.h" // for IsFileProtectedL
#include "upnpconstantdefs.h" // browse filtering and item element names
#include <upnpdlnaprotocolinfo.h> // for resolving object mimetype
#include "upnpavcontroller.h"
#include "upnpavbrowsingsession.h"
#include "upnpavdevice.h"
#include "upnpavdevicelist.h"

#include "upnpitemresolverobserver.h" // MUPnPItemResolverObserver
#include "upnpitemresolverfactory.h" // factory class
#include "upnpitemresolver.h" // MUPnPItemResolver

#include "upnptrackobserver.h"
#include "upnptrack.h"

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

// CONSTANTS
_LIT16( KUPnPPrefix, "upnp:" );   // Prefix for separate local/remote song
const TInt KUPnPPrefixLength = 5;
const TInt KCharCodeColon = 58;
const TInt KCharCodeSeparate = 42;
const TInt InitialTrackDuration = 1;
_LIT( KTimeFormatYearOnly, "%F%Y" );

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

// --------------------------------------------------------------------------
// CUPnPTrack::NewL
// 1st phase constructor.
// --------------------------------------------------------------------------
//
CUPnPTrack* CUPnPTrack::NewL( MUPnPAVController& aAvController )
    {
    __LOG( "CUPnPTrack::NewL" );
    CUPnPTrack* self = new( ELeave ) CUPnPTrack( aAvController );
    return self;
    }

// --------------------------------------------------------------------------
// CUPnPTrack::Delete
// deletor
// --------------------------------------------------------------------------
//
void CUPnPTrack::Delete()
    {
    __LOG1( "CUPnPTrack::Delete, state=%d", iState );
    if ( iState == EStateResolving )
        {
        // asynchronous delete - will be deleted after
        // asynchronous operation is complete. This is because the
        // S60 command can not be cancelled
        iState = EStateSelfDestruct;
        }
    else
        {
        delete this;
        }
    }

// --------------------------------------------------------------------------
// CUPnPTrack::CUPnPTrack
// Default constructor.
// --------------------------------------------------------------------------
// 
CUPnPTrack::CUPnPTrack( MUPnPAVController& aAvController )
    : iAvController( aAvController )
    , iQueriedAttributes()
    {
    iBrowsingSession = NULL;
    iOriginalURI = NULL;
    iMediaServer = NULL;
    iObjectId = NULL;
    iTrackObserver = NULL;
    // Use initial duration value (1). It will guarantee that in
    // case were remote device does not support duration query and playback
    // is unpaused, SetPosition is called with real value even
    // if remote player does not return real value for getposition
    // call. Note that SetPosition(0) is used when user really wants
    // to move to track beginning.
    iTrackDuration = InitialTrackDuration;
    iIsItemSolved = EFalse;
    iState = EStateIdle;
    }

// --------------------------------------------------------------------------
// CUPnPTrack::~CUPnPTrack
// destructor.
// --------------------------------------------------------------------------
//
CUPnPTrack::~CUPnPTrack()
    {
    __LOG( "CUPnPTrack::~CUPnPTrack()" );
    StopBrowsingSession();

    // Free memory of owned members
    delete iOriginalURI;
    delete iMediaServer;        
    delete iObjectId;
    delete iItemResolver;
    iItemResolver = 0;
    __LOG( "CUPnPTrack::~CUPnPTrack End" );
    }

// --------------------------------------------------------------------------
// CUPnPTrack::ResolveURIL
// Resolve local / remote URI.
// --------------------------------------------------------------------------
//
void CUPnPTrack::ResolveURIL( const TDesC& aCodedTrackUri,
    MUPnPTrackObserver& aTrackObserver,
    TPlaybackDirection aPlaybackDirection )
    {  
    __LOG( "CUPnPTrack::ResolveURI" );

    delete iOriginalURI;
    iOriginalURI = 0;
    delete iMediaServer;
    iMediaServer = 0;
    delete iObjectId;
    iObjectId = 0;
    iTrackObserver = &aTrackObserver;

    // Either local to remote or remote to remote
    if( aPlaybackDirection == EDirectionRemote )
        {
        if( aCodedTrackUri.Find( KUPnPPrefix ) == 0 )
            {
            // track is located in remote
            iTrackLocation = ETrackLocationRemote;
            // parse and save media server id and object id
            ParsePiecesL( aCodedTrackUri );
            // start a browsing session
            StartBrowsingSessionL();
            // create resolver 
            iItemResolver =
                UPnPItemResolverFactory::NewRemoteItemResolverL(
                *iObjectId, *iBrowsingSession, 
                iDefaultSelector, KFilterCommon );
            }
        else // Local stored. Save URI to local member
            {
            // track is located in local file system
            iTrackLocation = ETrackLocationLocal;
            // store original URI
            iOriginalURI = HBufC::NewL( aCodedTrackUri.Length() );
            iOriginalURI->Des().Copy( aCodedTrackUri );
			// check for DRM protection
			if ( UPnPFileUtility::IsFileProtectedL( iOriginalURI->Des() ) )
				{
				// call back directly with an error code
				iTrackObserver->ResolveURIComplete( KErrNotSupported );
				return;
				}
			else
				{
	            // create resolver.
	            iItemResolver =
	                UPnPItemResolverFactory::NewLocalItemResolverL(
						*iOriginalURI, iAvController, iFirstSelector,
						UPnPItemResolverFactory::EOmitDrmCheck );
				}
            }
        }
    else // Remote to local direction
        {
        // track is located in remote
        iTrackLocation = ETrackLocationRemote;
        // parse and save media server id and object id
        ParsePiecesL( aCodedTrackUri );
        // start a browsing session
        StartBrowsingSessionL();
        // create resolver
        iItemResolver =
            UPnPItemResolverFactory::NewDownloadItemResolverL(
            *iObjectId, iAvController, *iBrowsingSession, 
            iFirstSelector, KFilterCommon );
        }

    // Resolve remote item. Calls back to ResolveComplete
    iState = EStateResolving;
    TRAPD( e, iItemResolver->ResolveL( *this ); )
    if ( e != KErrNone )
        {
        if ( iState == EStateSelfDestruct )
            {
            __LOG( "CUPnPTrack: self-destructing" );
            delete this;
            }
        else
            {
            iState = EStateIdle;
            User::Leave( e );
            }
        }
    }

// --------------------------------------------------------------------------
// CUPnPTrack::StartBrowsingSessionL
// Finds the apropriate mediaserver and starts a browsing session
// --------------------------------------------------------------------------
//
void CUPnPTrack::StartBrowsingSessionL()
    {
    // Get list of media servers                 
    CUpnpAVDeviceList* devices = iAvController.GetMediaServersL();
    CleanupStack::PushL( devices );

    // Find out index of wanted media server from media server list 
    TInt index = KErrNotFound; 
    TInt count = devices->Count();

    for( TInt i = 0; i < count; i++ )
        {                                              
        // If media server id match.
        if( !iMediaServer->Compare( (*devices)[ i ]->Uuid() ) )
            {
            index = i;
            break;      
            }
        }

    // Leave if media server does not find by id 
    if( index == KErrNotFound )
        {
        __LOG1( "CUPnPTrack: Media server not found: %S",
            iMediaServer );
        User::Leave( KErrNotFound );    
        }

    // start a browsing session
    iBrowsingSession = &iAvController.StartBrowsingSessionL(
        *(*devices)[ index ] );
    CleanupStack::PopAndDestroy( devices );
    }

// --------------------------------------------------------------------------
// CUPnPTrack::StopBrowsingSession
// Finds the apropriate mediaserver and starts a browsing session
// --------------------------------------------------------------------------
//
void CUPnPTrack::StopBrowsingSession()
    {
    // Stop browsing session if exist.
    if( iBrowsingSession )
        {
        __LOG( "Stop browsing session" );
        iAvController.StopBrowsingSession( *iBrowsingSession );
        iBrowsingSession = 0;
        }
    }

// --------------------------------------------------------------------------
// CUPnPTrack::URI
// Return original URI of track.
// --------------------------------------------------------------------------
//  
const TDesC& CUPnPTrack::URI() const
    {
    __ASSERTD( iOriginalURI != 0,__FILE__, __LINE__ );
    return *iOriginalURI;
    }

// --------------------------------------------------------------------------
// CUPnPTrack::UpnpURI
// Return True UPNP URI of track.
// --------------------------------------------------------------------------
//  
const TDesC8& CUPnPTrack::UpnpURI() const
    {
    __ASSERTD( iIsItemSolved,__FILE__, __LINE__ );
    return iItemResolver->Resource().Value();
    }

// --------------------------------------------------------------------------
// CUPnPTrack::UpnpItem
// Return True UPNP item representing the track
// --------------------------------------------------------------------------
//  
const CUpnpItem& CUPnPTrack::UpnpItem() const
    {
    __ASSERTD( iIsItemSolved,__FILE__, __LINE__ );
    return iItemResolver->Item();
    }
    
// --------------------------------------------------------------------------
// CUPnPTrack::FilePath
// Returns the file path of local item 
// --------------------------------------------------------------------------
//  
const TDesC& CUPnPTrack::FilePath() const
    {
    __ASSERTD( iTrackLocation == ETrackLocationRemote, __FILE__, __LINE__ );
    __ASSERTD( iIsItemSolved,__FILE__, __LINE__ );
    return iItemResolver->Resource().FilePath();
    }

// --------------------------------------------------------------------------
// CUPnPTrack::IsRemote
// Return location of track. ETrue = remote. EFalse = local
// --------------------------------------------------------------------------
//  
TBool CUPnPTrack::IsRemote() const
    {
    return iTrackLocation == ETrackLocationRemote;
    }

// --------------------------------------------------------------------------
// CUPnPTrack::TrackDuration
// returns duration of the track
// --------------------------------------------------------------------------
// 
TInt CUPnPTrack::TrackDuration()
    {
    __LOG1( "CUPnPTrack::TrackDuration duration: %d", iTrackDuration );
    TInt ms = InitialTrackDuration;
    if ( iTrackDuration > InitialTrackDuration )
        {
        ms = iTrackDuration;
        }
    else if ( iIsItemSolved )
        {
        const CUpnpAttribute* attr = UPnPItemUtility
            ::FindAttributeByName( iItemResolver->Resource(),
             KAttributeDuration );
        if ( attr != 0 )
            {
            if ( UPnPItemUtility::UPnPDurationAsMilliseconds(
                attr->Value(), ms ) == KErrNone )
                {
                // store duration for quicker future queries
                iTrackDuration = ms;
                __LOG1( "store duration: %d", iTrackDuration );
                }
            }
        }
    return ms;
    }

// --------------------------------------------------------------------------
// CUPnPTrack::SetTrackDuration
// overrides duration of the track
// --------------------------------------------------------------------------
// 
void CUPnPTrack::SetTrackDuration( TInt aMilliseconds )
    {
    iTrackDuration = aMilliseconds;
    }

// --------------------------------------------------------------------------
// CUPnPTrack::GetMetaDataL
// Get metadata information for track from media server
// --------------------------------------------------------------------------
//  
void CUPnPTrack::GetMetaDataL( const TArray<TMPXAttribute>& aAttrs, 
    MMPXPlaybackPluginObserver& aObs )
    {
    // Check if remote track
    if( iTrackLocation == ETrackLocationLocal )
        {
        __LOG( "CUPnPTrack::GetMetaData - No metadata for local track!" );
        User::Leave( KErrNotSupported );
        }

    if ( iIsItemSolved )
        {
        __LOG( "CUPnPTrack::GetMetaDataL" );
        DeliverMedataL( aAttrs, aObs );
        }
    else
        {
        __LOG( "CUPnPTrack::GetMetaDataL - pending" );
        iMetadataObserver = &aObs;
        for( TInt i = 0; i < aAttrs.Count(); ++i )
            {
            iQueriedAttributes.AppendL( aAttrs[i] );
            }
        }
    }

// --------------------------------------------------------------------------
// CUPnPTrack::SendMediaChangedEventL
// --------------------------------------------------------------------------
// 
void CUPnPTrack::SendMediaChangedEventL(
    MMPXPlaybackPluginObserver& aObs )
    {
    RArray<TMPXAttribute> attrs;
    CleanupClosePushL( attrs );
    attrs.AppendL( KMPXMediaGeneralTitle );
    attrs.AppendL( KMPXMediaMusicArtist );
    attrs.AppendL( KMPXMediaMusicAlbum );
    attrs.AppendL( KMPXMediaMusicGenre );
    attrs.AppendL( KMPXMediaGeneralDate );
    attrs.AppendL( KMPXMediaMusicYear );
    attrs.AppendL( KMPXMediaGeneralComment );
    attrs.AppendL( KMPXMediaGeneralMimeType );

    // Create and fill CMPXMedia class 
    RArray<TInt> suppIds;
    CleanupClosePushL( suppIds );
    suppIds.AppendL( KMPXMediaIdMusic );
    suppIds.AppendL( KMPXMediaIdGeneral );
    suppIds.AppendL( KMPXMediaIdAudio );
    CMPXMedia* media = CMPXMedia::NewL( suppIds.Array() );
    CleanupStack::PopAndDestroy( &suppIds );
    CleanupStack::PushL( media );
    FillMediaFromItemL( *media, attrs.Array() );
    
    // create an MPX message
    CMPXMessage* msg = CMPXMessage::NewL();
    CleanupStack::PushL( msg );
    msg->SetTObjectValueL<TMPXMessageId>(
        KMPXMessageGeneralId, KMPXMessagePbMediaChanged );
    msg->SetCObjectValueL<CMPXMedia>(
        KMPXMessagePbMedia, media );

    // send message
    aObs.HandlePlaybackMessage( *msg );

    CleanupStack::PopAndDestroy( msg );
    CleanupStack::PopAndDestroy( media );
    CleanupStack::PopAndDestroy( &attrs );
    }

// --------------------------------------------------------------------------
// CUPnPTrack::DeliverMedatataL
// --------------------------------------------------------------------------
// 
void CUPnPTrack::DeliverMedataL( const TArray<TMPXAttribute>& aAttrs, 
    MMPXPlaybackPluginObserver& aObs, TInt aError )
    {
    __LOG( "CUPnPTrack::DeliverMedatata");

    // Create and fill CMPXMedia class 
    RArray<TInt> suppIds;
    CleanupClosePushL( suppIds );
    suppIds.AppendL( KMPXMediaIdMusic );
    suppIds.AppendL( KMPXMediaIdGeneral );
    suppIds.AppendL( KMPXMediaIdAudio );
    CMPXMedia* media = CMPXMedia::NewL( suppIds.Array() );
    CleanupStack::PopAndDestroy( &suppIds );        
    CleanupStack::PushL( media );

    if ( aError == KErrNone )
        {
        FillMediaFromItemL( *media, aAttrs );
        }

    // Return metadata
    aObs.HandleMedia( *media, aError );
    CleanupStack::PopAndDestroy( media );
    }

// --------------------------------------------------------------------------
// CUPnPTrack::FillMediaFromItemL
// --------------------------------------------------------------------------
// 
void CUPnPTrack::FillMediaFromItemL( CMPXMedia& aMedia,
    const TArray<TMPXAttribute>& aAttrs )
    {
    __ASSERTD( iIsItemSolved,__FILE__, __LINE__ );

    // Fill metadata 
    const CUpnpElement* elem;
    // Song title
    if( Exists( aAttrs, KMPXMediaGeneralTitle ) )
        {
        __LOG( "CUPnPTrack: Metadata: Title");
        aMedia.SetTextValueL(
            KMPXMediaGeneralTitle, *To16LC( 
            iItemResolver->Item().Title() ) );
        CleanupStack::PopAndDestroy();
        }
    // Artist
    if( Exists( aAttrs, KMPXMediaMusicArtist ) )
        {
        if ( ( elem = UPnPItemUtility::FindElementByName(
            iItemResolver->Item(), KElementArtist ) ) != 0 )
            {
            __LOG( "CUPnPTrack: Metadata: Artist" );
            aMedia.SetTextValueL(
                KMPXMediaMusicArtist, *To16LC( elem->Value() ) );
            CleanupStack::PopAndDestroy();
            }
        else if ( ( elem = UPnPItemUtility::FindElementByName(
            iItemResolver->Item(), KElementCreator ) ) != 0 )
            {
            __LOG( "CUPnPTrack: Metadata Creator" );
            aMedia.SetTextValueL(
                KMPXMediaMusicArtist, *To16LC( elem->Value() ) );
            CleanupStack::PopAndDestroy();
            }
        }
    // Album
    if( Exists( aAttrs, KMPXMediaMusicAlbum ) )
        {
        if ( ( elem = UPnPItemUtility::FindElementByName(
            iItemResolver->Item(), KElementAlbum ) ) != 0 )
            {
            __LOG( "CUPnPTrack: Metadata: Album");
            aMedia.SetTextValueL(
                KMPXMediaMusicAlbum, *To16LC( elem->Value() ) );
            CleanupStack::PopAndDestroy();
            }
        }
    // Genre
    if( Exists( aAttrs, KMPXMediaMusicGenre ) )
        {
        if ( ( elem = UPnPItemUtility::FindElementByName(
            iItemResolver->Item(), KElementGenre ) ) != 0 )
            {
            __LOG( "CUPnPTrack: Metadata: Genre" );
            aMedia.SetTextValueL(
                KMPXMediaMusicGenre, *To16LC( elem->Value() ) );
            CleanupStack::PopAndDestroy();
            }
        }
    // Date / Year
    if( ( elem = UPnPItemUtility::FindElementByName(
          iItemResolver->Item(), KElementDate ) ) != 0 )
        {
        TTime timestamp;
        TInt conversionError =
            UPnPItemUtility::UPnPDateAsTTime( elem->Value(), timestamp );
        if ( conversionError == KErrNone )
            {
            if ( Exists( aAttrs, KMPXMediaGeneralDate ) )
                {
                __LOG( "CUPnPTrack: Metadata: Date" );
                aMedia.SetTextValueL(
                    KMPXMediaGeneralDate, iTempBuf );
                }
            if ( Exists( aAttrs, KMPXMediaMusicYear ) )
                {
                __LOG( "CUPnPTrack: Metadata: Year" );
                timestamp.FormatL( iTempBuf, KTimeFormatYearOnly );
                aMedia.SetTextValueL(
                    KMPXMediaMusicYear, iTempBuf );
                }
            }
        }
    // Duration
    if( Exists( aAttrs, KMPXMediaGeneralDuration ) )
        {
        TInt duration = TrackDuration();
        if ( duration >= 0 )
            {
            aMedia.SetTObjectValueL<TInt>(
                KMPXMediaGeneralDuration, duration );
            }
        }
    // Size
    if( Exists( aAttrs, KMPXMediaGeneralSize ) )
        {
        const CUpnpAttribute* attr = UPnPItemUtility
            ::FindAttributeByName( iItemResolver->Resource(),
             KAttributeSize );
        if ( attr != 0 )
            {
            __LOG( "CUPnPTrack: Metadata: Size" );
            TInt size;
            TLex8 sizeconvert( attr->Value() );
            if ( sizeconvert.Val( size ) == KErrNone )
                {
                aMedia.SetTObjectValueL<TInt>(
                    KMPXMediaGeneralSize, size );
                }
            }
        }
    // Mimetype
    if( Exists( aAttrs, KMPXMediaGeneralMimeType ) )
        {        
        const CUpnpAttribute* attr = UPnPItemUtility
            ::FindAttributeByName( iItemResolver->Resource(),
             KAttributeProtocolInfo );
        if ( attr != 0 )
            {
            __LOG( "CUPnPTrack: Metadata: MimeType" );
            CUpnpDlnaProtocolInfo* pInfo =
                CUpnpDlnaProtocolInfo::NewL( attr->Value() );
            CleanupStack::PushL( pInfo );
            aMedia.SetTextValueL(
                KMPXMediaGeneralMimeType, *To16LC( pInfo->ThirdField() ) );
            CleanupStack::PopAndDestroy();
            CleanupStack::PopAndDestroy( pInfo );
            pInfo = NULL;
            }
        }
    }

// --------------------------------------------------------------------------
// CUPnPTrack::Exists
// --------------------------------------------------------------------------
// 
TBool CUPnPTrack::Exists( const TArray<TMPXAttribute>& aAttrs,
    const TMPXAttributeData& aAttrData ) const
    {
    TBool found = EFalse;
    for( TInt i = 0; i < aAttrs.Count() && !found; ++i )
        {
        if ( aAttrs[i].ContentId() == aAttrData.iContentId &&
            aAttrs[i].AttributeId() & aAttrData.iAttributeId )
            {
            found = ETrue;
            }
        }
    return found;
    }

// --------------------------------------------------------------------------
// CUPnPTrack::To16LC
// --------------------------------------------------------------------------
// 
const HBufC16* CUPnPTrack::To16LC( const TDesC8& aText )
    {
    HBufC16* result = 0;
    result = EscapeUtils::ConvertToUnicodeFromUtf8L( aText );
    CleanupStack::PushL( result );
    return result;
    }

// --------------------------------------------------------------------------
// callbacks from MUPnPItemResolverObserver
// --------------------------------------------------------------------------
//  
void CUPnPTrack::ResolveComplete( const MUPnPItemResolver& /*aResolver*/,
    TInt aError )
    {
    __LOG1( "CUPnPTrack::ResolveComplete err: %d", aError );
    iIsItemSolved = ETrue;
    if ( iState == EStateResolving )
        {
        iState = EStateReady;

        // handle pending metadata query
        if ( iTrackLocation == ETrackLocationRemote && iMetadataObserver )
            {
            __LOG( "Handle pending metadata query");
             TRAP_IGNORE( 
                DeliverMedataL( iQueriedAttributes.Array(), *iMetadataObserver,
                aError ) );
             iMetadataObserver = 0;
             iQueriedAttributes.Reset();
            }

        // call back
        MUPnPTrackObserver& observer = *iTrackObserver;
        iTrackObserver = 0;
        observer.ResolveURIComplete( aError );
        }
    else if ( iState == EStateSelfDestruct )
        {
        __LOG( "CUPnPTrack: self-destructing" );
        delete this;
        }
    }
    
// --------------------------------------------------------------------------
// Private methods of CUPnPTrack
// --------------------------------------------------------------------------

// --------------------------------------------------------------------------
// CUPnPTrack::ParsePiecesL
// Parse and save media server id and object id from given descriptor
// --------------------------------------------------------------------------
//    
void CUPnPTrack::ParsePiecesL( const TDesC& aSong )
    {    
    // Delete if already exist
    if( iMediaServer )
        {
        delete iMediaServer;
        iMediaServer = 0;
        }
    if( iObjectId )
        {
        delete iObjectId;
        iObjectId = 0;
        }
    
    // Leave if argument is not valid
    if( aSong.Length() < KUPnPPrefixLength )
        {
        User::Leave( KErrArgument );
        }
        
    TInt lenght = aSong.Length();
    TInt position = 0;
    TChar colon( KCharCodeColon );
    TChar separate( KCharCodeSeparate );
        
    // At first separe "upnp:" prefix from descriptor 
    position = aSong.Locate( colon );   
    TPtrC tmp = aSong.Mid( position + 1, (lenght - KUPnPPrefixLength ) );
    
    // Get media server id
    position = tmp.Locate( separate );
    // Leave if separator character not found
    if( position == KErrNotFound )
        {
        User::Leave( KErrNotFound );
        }
    TPtrC mediaserverId = tmp.Left( position );
    iMediaServer = HBufC8::NewL( mediaserverId.Length() );
    iMediaServer->Des().Copy( mediaserverId );
        
    // Get object id
    TPtrC objId = tmp.Mid( position + 1, ( (tmp.Length() 
        - mediaserverId.Length() ) - 1 ) ); 
    iObjectId = HBufC8::NewL( objId.Length() );
    iObjectId->Des().Copy( objId );
    }