mpx/commonframework/common/src/mpxmedia.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Thu, 17 Dec 2009 08:55:47 +0200
changeset 0 a2952bb97e68
permissions -rw-r--r--
Revision: 200949 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:  Implementation of media
*
*/


#include <mpxlog.h>
#include <mpxuser.h>
#include "mpxmedia.h"
#include "mpxmediaarray.h"
#include "mpxcollectionpath.h"

// -----------------------------------------------------------------------------
// CMPXMedia::NewL
// -----------------------------------------------------------------------------
//
EXPORT_C CMPXMedia* CMPXMedia::NewL()
    {
    CMPXMedia* m=new(ELeave)CMPXMedia();
    CleanupStack::PushL(m);
    m->CMPXMediaBase::ConstructL();
    CleanupStack::Pop(m);
    return m;
    }

// -----------------------------------------------------------------------------
// CMPXMedia::NewL
// -----------------------------------------------------------------------------
//
EXPORT_C CMPXMedia* CMPXMedia::NewL(const TArray<TInt>& aSupportedIds)
    {
    CMPXMedia* m=new(ELeave)CMPXMedia();
    CleanupStack::PushL(m);
    m->ConstructL(aSupportedIds);
    CleanupStack::Pop(m);
    return m;
    }

// -----------------------------------------------------------------------------
// CMPXMedia::NewL
// -----------------------------------------------------------------------------
//
EXPORT_C CMPXMedia* CMPXMedia::NewL(RReadStream& aStream)
    {
    CMPXMedia* m=new(ELeave)CMPXMedia();
    CleanupStack::PushL(m);
    m->ConstructL(aStream);
    CleanupStack::Pop(m);
    return m;
    }

// -----------------------------------------------------------------------------
// CMPXMedia::NewL
// -----------------------------------------------------------------------------
//
EXPORT_C CMPXMedia* CMPXMedia::NewL(TInt aDataHandle)

    {
    CMPXMedia* m=new(ELeave)CMPXMedia();
    CleanupStack::PushL(m);
    m->CMPXMediaBase::ConstructL(aDataHandle);
    CleanupStack::Pop(m);
    return m;
    }

// -----------------------------------------------------------------------------
// CMPXMedia::NewL
// -----------------------------------------------------------------------------
//
EXPORT_C CMPXMedia* CMPXMedia::NewL(const CMPXMedia& aMedia)
    {
    CMPXMedia* m=new(ELeave)CMPXMedia();
    CleanupStack::PushL(m);
    m->CMPXMediaBase::ConstructL(aMedia);
    CleanupStack::Pop(m);
    return m;
    }

// -----------------------------------------------------------------------------
// CMPXMedia::CopyL
// -----------------------------------------------------------------------------
//
EXPORT_C CMPXMedia* CMPXMedia::CopyL(const CMPXMedia& aMedia)
    {
    CMPXMedia* m=new(ELeave)CMPXMedia();
    CleanupStack::PushL(m);
    m->CopyConstructL(aMedia);
    CleanupStack::Pop(m);
    return m;
    }

// ----------------------------------------------------------------------------
// Overloaded assignment operator
// ----------------------------------------------------------------------------
//
EXPORT_C CMPXMedia& CMPXMedia::operator=(const CMPXMedia& aMedia)
    {
//    MPX_FUNC_EX("CMPXMedia::operator=()");
    MPX_ASSERT(aMedia.iData&&aMedia.iDataHandle);
    MPX_ASSERT(iClientHandle);
    //
    if (this!=&aMedia)
        {
        Clear();
        iDataHandle=aMedia.iDataHandle;
        iData=aMedia.iData;
        iData->AddRef(iClientHandle);
        } // otherwise assign itself
    return *this;
    }

// -----------------------------------------------------------------------------
// Destructor
// -----------------------------------------------------------------------------
//
EXPORT_C CMPXMedia::~CMPXMedia()
    {
    iAttributes.Close();
    }

// -----------------------------------------------------------------------------
// CMPXMedia::HeapMemoryInfoL
// -----------------------------------------------------------------------------
//
EXPORT_C void CMPXMedia::HeapMemoryInfoL( TInt& aTotal, TInt& aUsed )
    {
    return MMPXData::HeapMemoryInfoL( aTotal, aUsed);
    }

// -----------------------------------------------------------------------------
// Externalize
// -----------------------------------------------------------------------------
//
EXPORT_C void CMPXMedia::ExternalizeL(RWriteStream& aStream) const
    {
    DoExternalizeL(aStream,MMPXData::EMedia);
    }

// -----------------------------------------------------------------------------
// Internalize
// -----------------------------------------------------------------------------
//
EXPORT_C void CMPXMedia::InternalizeL(RReadStream& aStream)
    {
    DoInternalizeL(aStream,MMPXData::EMedia);
    }

// -----------------------------------------------------------------------------
// Clears data
// -----------------------------------------------------------------------------
//
EXPORT_C void CMPXMedia::Reset()
    {
//    MPX_FUNC_EX("CMPXMedia::Reset()");
    MPX_ASSERT(iClientHandle&&iData);
    //
    ResetLocal(); // Local data
    iData->Reset(iClientHandle); // Clears heap data for this object
    }

// -----------------------------------------------------------------------------
// Possible content IDs that denote the type of content the source of this
// object can supply;
// -----------------------------------------------------------------------------
//
EXPORT_C const TArray<TInt> CMPXMedia::SupportedIds() const
    {
    MPX_ASSERT(iClientHandle&&iData);
    return iData->SupportedIds(iClientHandle);
    }

// -----------------------------------------------------------------------------
// The attributes provided in this media object
// -----------------------------------------------------------------------------
//
EXPORT_C const TArray<TMPXAttribute> CMPXMedia::Attributes() const
    {
    const_cast<CMPXMedia*>(this)->RefreshAttributes();
    return iAttributes.Array();
    }

// -----------------------------------------------------------------------------
// Does this object contain the value for a given attribute
// -----------------------------------------------------------------------------
//
EXPORT_C TBool CMPXMedia::IsSupported(const TMPXAttribute& aAttribute) const
    {
    MPX_ASSERT(iClientHandle&&iData);
    return KErrNotFound!=iData->Index(iClientHandle,aAttribute);
    }

// -----------------------------------------------------------------------------
// The number of attribute values provided in this media object
// -----------------------------------------------------------------------------
//
EXPORT_C TInt CMPXMedia::Count() const
    {
    return CMPXMediaBase::Count();
    }

// -----------------------------------------------------------------------------
// The attribute for a specific index
// -----------------------------------------------------------------------------
//
EXPORT_C const TMPXAttribute& CMPXMedia::Attribute(TInt aIndex) const
    {
    MPX_ASSERT(iClientHandle&&iData);
    MPX_ASSERT(aIndex>=0&&aIndex<Count());
    //
    return iData->Attribute(iClientHandle,aIndex);
    }

// -----------------------------------------------------------------------------
// The attributes set for a specific content
// -----------------------------------------------------------------------------
//
EXPORT_C TUint CMPXMedia::AttributesSet(TInt aContentId) const
    {
    const_cast<CMPXMedia*>(this)->RefreshAttributes();
    TUint attributesSet(0);
    for (TInt i=iAttributes.Count();--i>=0;)
        {
        TMPXAttribute attr(iAttributes[i]);
        if (attr.ContentId()==aContentId)
            {
            attributesSet|=attr.AttributeId();
            }
        }
    return attributesSet;
    }

// -----------------------------------------------------------------------------
// The index of a given attribute
// -----------------------------------------------------------------------------
//
EXPORT_C TInt CMPXMedia::Index(const TMPXAttribute& aAttribute) const
    {
    MPX_ASSERT(iClientHandle&&iData);
    return iData->Index(iClientHandle,aAttribute);
    }

// -----------------------------------------------------------------------------
// The type of data stored for the attribute
// -----------------------------------------------------------------------------
//
EXPORT_C TMPXAttributeType CMPXMedia::Type(TInt aIndex) const
    {
    MPX_ASSERT(iClientHandle&&iData);
    MPX_ASSERT(aIndex>=0&&aIndex<Count());
    //
    return iData->AttributeType(iClientHandle,aIndex);
    }

// -----------------------------------------------------------------------------
// The type of data stored for the attribute
// -----------------------------------------------------------------------------
//
EXPORT_C TMPXAttributeType CMPXMedia::Type(const TMPXAttribute& aAttribute) const
    {
    MPX_ASSERT(iClientHandle&&iData);
    TMPXAttributeType type(EMPXTypeUnknown);
    TInt index(Index(aAttribute));
    if (KErrNotFound!=index)
        {
        type = Type(index);
        }
    return type;
    }

// -----------------------------------------------------------------------------
// The value for a specific attribute
// -----------------------------------------------------------------------------
//
EXPORT_C const TDesC& CMPXMedia::ValueText(const TMPXAttribute& aAttribute) const
    {
    TPtrC* text=Value<TPtrC>(aAttribute);
    return text?(const TDesC&)*text:KNullDesC;
    }

// -----------------------------------------------------------------------------
// Add a new attribute value to this object, or modifies existing
// value if already present
// -----------------------------------------------------------------------------
//
EXPORT_C  void CMPXMedia::SetTextValueL(
    const TMPXAttribute& aAttribute,
    const TDesC& aValue)
    {
    TPtrC8 data((TUint8*)aValue.Ptr(),aValue.Size());
    SetValueL(aAttribute,data,EMPXTypeText);
    }

// -----------------------------------------------------------------------------
// Merges in the attributes of the provided media
// -----------------------------------------------------------------------------
//
EXPORT_C void CMPXMedia::MergeMediaL( const CMPXMedia& aMedia )
    {
    // Do not merge the same data handle
    if( Data() != aMedia.Data() )
        {
        for ( TInt i = 0; i < aMedia.Count(); i++ )
            {
            TMPXAttributeType type( aMedia.Type( i ));
            TMPXAttribute att( aMedia.Attribute( i ));
            // Need to handle text differently since it's
            // possible to have KNullDesC, which will result
            // in an invalid TPtrC.
            if ( EMPXTypeText == type )
                {
                const TDesC& t( aMedia.ValueText( att ));
                if ( t == KNullDesC )
                    {
                    // Cannot use reference to KNullDesC, must
                    // use the literal directly.
                    SetTextValueL( att, KNullDesC );
                    }
                else
                    {
                    SetTextValueL( att, t );
                    }
                }
            else
                {
                TPtrC8 ptr( aMedia.iData->Value( aMedia.iClientHandle, i ));
                SetValueL( att, ptr, type );
                }
            }
        }
    }

// -----------------------------------------------------------------------------
// Compares if the specified media's attribute matches this one
// -----------------------------------------------------------------------------
//
EXPORT_C TBool CMPXMedia::Match(
    const CMPXMedia& aMedia,
    const TMPXAttribute& aAtt )
    {
    TBool result( EFalse );
    TInt myIndex( Index( aAtt ));
    if ( KErrNotFound != myIndex )
        {
        TInt index( aMedia.Index( aAtt ));
        if ( KErrNotFound != index )
            {
            if ( Type( myIndex ) == aMedia.Type( index ))
                {
                TPtrC8 myPtr( iData->Value( iClientHandle, myIndex ));
                TPtrC8 ptr( aMedia.iData->Value( aMedia.iClientHandle, index ));
                result = ( myPtr == ptr );
                }
            }
        }
    return result;
    }

// -----------------------------------------------------------------------------
// CMPXMedia::Delete
// -----------------------------------------------------------------------------
//
EXPORT_C void CMPXMedia::Delete(const TMPXAttribute& aAttribute)
    {
//    MPX_FUNC_EX("CMPXMedia::Delete(const TMPXAttribute& aAttribute)");
    Delete(iData->Index(iClientHandle,aAttribute));
    }

// -----------------------------------------------------------------------------
// CMPXMedia::Delete
// -----------------------------------------------------------------------------
//
EXPORT_C void CMPXMedia::Delete(TInt aIndex)
    {
//    MPX_FUNC_EX("CMPXMedia::Delete(TInt aIndex)");
    if (KErrNotFound != aIndex)
        {
        MPX_ASSERT(aIndex>=0&&aIndex<Count());
        DeleteLocal(aIndex);
        iData->Delete(iClientHandle,aIndex);
        } // do nothing. the same behaviour as the v1 although it should panic
    }

// -----------------------------------------------------------------------------
// CMPXMedia::ConstructL
// -----------------------------------------------------------------------------
//
void CMPXMedia::ConstructL(const TArray<TInt>& aSupportedIds)
    {
    CMPXMediaBase::ConstructL();
    User::LeaveIfError(iData->SetSupportedIds(iClientHandle,aSupportedIds));
    }

// -----------------------------------------------------------------------------
// CMPXMedia::ConstructL
// -----------------------------------------------------------------------------
//
void CMPXMedia::ConstructL(RReadStream& aStream)
    {
    MPX_ASSERT(!iData&&!iDataHandle);
    InternalizeL(aStream);
    }

// -----------------------------------------------------------------------------
// CMPXMedia::SetValueL
// -----------------------------------------------------------------------------
//
EXPORT_C void CMPXMedia::SetValueL(
    const TMPXAttribute& aAttribute,
    const TDesC8& aValue,
    TMPXAttributeType aType)
    {
    MPX_ASSERT(iData&&iClientHandle);
    //
    LockHeapLC();
    TInt i=iData->Index(iClientHandle,aAttribute);
    if (i==KErrNotFound)
        {
        User::LeaveIfError(iData->Append(iClientHandle,aAttribute,aType,aValue));
        }
     else
        {
        DeleteLocal(i);
        iData->Set(iClientHandle,aAttribute,aType,aValue,i);
        }
    CleanupStack::PopAndDestroy(); //unlock heap
    }

// -----------------------------------------------------------------------------
// CMPXMedia::ValuePtr. Returns NULL if (a) there is no such object with the
// given attribute; (b) object cannot be created (e.g. no memory); (c) it's an
// arbitrary CBase object (only CMPXMedia, CMPXMediaArray, and CMPXCollectionPath
// are supported. Otherwise, returns a pointer to the object which is also stored
// locally
// -----------------------------------------------------------------------------
//
EXPORT_C TAny* CMPXMedia::ValuePtr(const TMPXAttribute& aAttribute) const
    {
    MPX_ASSERT(iData&&iClientHandle);
    MMPXData::LockHeap( iClientHandle );
    TAny* obj=NULL;
    TInt index=iData->Index(iClientHandle,aAttribute);
    TMPXAttributeType type=EMPXTypeUnknown;

    if (index!=KErrNotFound) // Check if the value exist or not
        {
        type=iData->AttributeType(iClientHandle,index);
        // Check local values to see if there and current
        //
        TInt uid=iData->Uid(iClientHandle,index);
        const TValue* v=LocalValue(uid);
        if (!v)
            {
            TPtrC8 data=iData->Value(iClientHandle,index);
            TInt size=data.Size();
            const TAny* ptr=data.Ptr();
            //
            switch(type)
                {
            case EMPXTypeText:
                obj=new TPtrC((TUint16*)ptr,size/2);
                break;
                //
            case EMPXTypeCObject:
                TRAP_IGNORE(obj=ValueCObjectL(data));
                break;
                //
            case EMPXTypeError: // Error type is TInt, flow down
            case EMPXTypeTObject:
                //
                // Create a decriptor pointing to the data. But the pointer
                // within the descriptor must be returned by this method
                //
                 obj=new TPtrC8((TUint8*)ptr,size);
                break;
                //
            default:
                MPX_ASSERT(0);
                break;
                }
            if (obj)
                {
                CMPXMedia& theMedia=*const_cast<CMPXMedia*>(this);
                TInt err=theMedia.SetLocal(TValue(obj,uid,type)); // Add new one
                if (err!=KErrNone)
                    {
                    theMedia.DeletePtr(obj,type);
                    obj=NULL;
                    }
                }
            }
        else
            {
            obj=v->iValue;
            }
        }
    MMPXData::UnlockHeap(iClientHandle);
    return (type==EMPXTypeTObject||type==EMPXTypeError)?(obj?(TAny*)static_cast<TPtrC8*>(obj)->Ptr():NULL):obj;
    }

EXPORT_C TMPXAttributeType CMPXMedia::GetValue(const TMPXAttribute& aAttribute, TDes8& aValue) const
    {
    MPX_ASSERT(iData&&iClientHandle);
    MMPXData::LockHeap( iClientHandle );
    TInt index=iData->Index(iClientHandle,aAttribute);
    TMPXAttributeType type=EMPXTypeUnknown;
    
    if (index!=KErrNotFound) // Check if the value exist or not
        {
        type=iData->AttributeType(iClientHandle,index);
        aValue = iData->Value(iClientHandle,index).Left(aValue.MaxLength());
        }
    MMPXData::UnlockHeap(iClientHandle);
    return type;
    }

// -----------------------------------------------------------------------------
// CMPXMedia::RefreshAttributes
// -----------------------------------------------------------------------------
//
void CMPXMedia::RefreshAttributes()
    {
    // Reconstructs array of attributes
    //
    iAttributes.Reset();
    for (TInt i=iData->Count(iClientHandle);--i>=0;)
        {
        (void)iAttributes.Append(iData->Attribute(iClientHandle,i));
        }
    }

// -----------------------------------------------------------------------------
// CMPXMedia::ResetLocal
// -----------------------------------------------------------------------------
//
void CMPXMedia::ResetLocal()
    {
    CMPXMediaBase::ResetLocal();
    iAttributes.Reset();
    }

// -----------------------------------------------------------------------------
// CMPXMedia::ValueCObjectL
// -----------------------------------------------------------------------------
//
TAny* CMPXMedia::ValueCObjectL(const TDesC8& aData) const
    {
    TAny* obj=NULL;
    TInt size=aData.Size();
    TUint* ptr=(TUint*)aData.Ptr();

#ifdef _DEBUG
    const TBool ptrAddrIsOnBoundary = ((TUint)ptr & 3) == 0;

    // Only dereference 4-byte word on 4-byte word boundary
    MPX_ASSERT(ptrAddrIsOnBoundary); // assert if this is not the case
#endif

    MMPXData::TMPXObjectType t=*(MMPXData::TMPXObjectType*)ptr;
    switch(t)
        {
        case MMPXData::EMedia:
            MPX_ASSERT(size==sizeof(TInt)+sizeof(TUint)); // i.e 8 bytes
            obj=CMPXMedia::NewL(*++ptr);
            break;
            //
        case MMPXData::EMediaArray:
            MPX_ASSERT(size==sizeof(TInt)+sizeof(TUint)); // i.e 8 bytes
            obj=ValueL<CMPXMediaArray>(aData);
            break;
            //
        case MMPXData::EPath:
            obj=ValueL<CMPXCollectionPath>(aData);
            break;
            //
        default:
            //
            // obj=NULL, i.e. arbitrary C objects
            // ARE NOT SUPPORTED by this method
            //
            MPX_ASSERT(0); // For now, to catch clients that use this
            break;
            }
        return obj;
    }

// -----------------------------------------------------------------------------
// CMPXMedia::SetErrorL
// -----------------------------------------------------------------------------
EXPORT_C void CMPXMedia::SetErrorL(const TMPXAttribute& aAttribute, TInt aError)
    {
    TPtrC8 value((TUint8*)&aError,sizeof(TInt));
    SetValueL(aAttribute,value,EMPXTypeError);
    }

// -----------------------------------------------------------------------------
// CMPXMedia::Error
// -----------------------------------------------------------------------------
EXPORT_C TInt CMPXMedia::Error(const TMPXAttribute& aAttribute) const
    {
    if (Type(aAttribute)==EMPXTypeError)
        {
        TInt* v=(TInt*)ValuePtr(aAttribute);
        return v?*v:KErrNone; // return KErrNone if none exists!
        }
    else
        return KErrNone;
    }

// END OF FILE