mpxplugins/serviceplugins/collectionplugins/mpxsqlitedbcommon/src/mpxdbcommonutil.cpp
branchRCL_3
changeset 53 3de6c4cf6b67
child 56 2cbbefa9af78
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mpxplugins/serviceplugins/collectionplugins/mpxsqlitedbcommon/src/mpxdbcommonutil.cpp	Wed Sep 01 12:32:02 2010 +0100
@@ -0,0 +1,1310 @@
+/*
+* 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:  The class CMPXDbCommonUtil which contains utilities functions
+*
+*/
+
+
+// INCLUDE FILES
+#include <bautils.h>
+#include <caf/data.h>
+#include <caf/virtualpathptr.h>
+#include <hash.h>
+#include <apgcli.h>
+#include <apmstd.h>
+#include <sqldb.h>
+
+#include <mpxmediageneraldefs.h>
+#include <mpxmediamusicdefs.h>
+#include <mpxmediaaudiodefs.h>
+#include <mpxmediadrmdefs.h>
+#include <mpxmediacollectiondetaildefs.h>
+#include <mpxmedia.h>
+#include <mpxmediaarray.h>
+#include <mpxlog.h>
+
+#include "mpxdbcommonstd.h"
+#include "mpxdbcommondef.h"
+#include "mpxdbcommonutil.h"
+
+// CONSTANTS
+_LIT(KPathStart, ":\\");
+
+// ============================ FILE EXTENSION TO MIME MAP ==============================
+
+// ----------------------------------------------------------------------------------------------------------
+// Statically allocated Mime Map
+// ----------------------------------------------------------------------------------------------------------
+//
+
+_LIT( KExtensionAac,    "aac" );
+_LIT( KExtensionAif,    "aif"); 
+_LIT( KExtensionAifc,   "aifc"); 
+_LIT( KExtensionAiff,   "aiff");
+_LIT( KExtensionAmr,    "amr" );
+_LIT( KExtensionAu,     "au" );
+_LIT( KExtensionAwb,    "awb" );
+_LIT( KExtensionMid,    "mid" );
+_LIT( KExtensionMidi,   "midi" );
+_LIT( KExtensionMka,    "mka" );
+_LIT( KExtensionMp3,    "mp3" );
+_LIT( KExtensionOgg,    "ogg");
+_LIT( KExtensionRa,     "ra"); 
+_LIT( KExtensionRam,    "ram"); 
+_LIT( KExtensionRmi,    "rmi"); 
+_LIT( KExtensionSnd,    "snd" );
+_LIT( KExtensionSpMid,  "spmid" );
+_LIT( KExtensionWav,    "wav" );
+_LIT( KExtensionWma,    "wma" );
+
+_LIT8( KMimeTypeAac,      "audio/aac" );
+_LIT8( KMimeTypeAiff,     "audio/x-aiff");
+_LIT8( KMimeTypeAmr,      "audio/amr" );
+_LIT8( KMimeTypeAu,       "audio/au" );
+_LIT8( KMimeTypeAwb,      "audio/amr-wb" );
+_LIT8( KMimeTypeBasic,    "audio/basic");
+_LIT8( KMimeTypeMatroska, "audio/x-matroska");
+_LIT8( KMimeTypeMid,      "audio/mid");
+_LIT8( KMimeTypeMidi,     "audio/midi" );
+_LIT8( KMimeTypeMpeg,     "audio/mpeg" );
+_LIT8( KMimeTypeOgg,      "audio/ogg");
+_LIT8( KMimeTypeReal,     "audio/x-pn-realaudio");
+_LIT8( KMimeTypeSpMidi,   "audio/sp-midi" );
+_LIT8( KMimeTypeWav,      "audio/wav" ); 
+_LIT8( KMimeTypeWma,      "audio/x-ms-wma");
+
+struct TMimeMapItem {
+	const TDesC  * iExt;
+	const TDesC8 * iType;
+};
+
+// We need to explicitly cast here as LitC::operator& requires writable DLL data (even though it is just a cast)
+#define MIME_MAP_ITEM(ext,type) { &REINTERPRET_CAST(const TDesC&, ext), &REINTERPRET_CAST(const TDesC8&, type) }
+
+// THIS ARRAY MUST BE SORTED BY EXTENSION
+static const TMimeMapItem KMimeMap [] = {
+    MIME_MAP_ITEM( KExtensionAac,   KMimeTypeAac),
+    MIME_MAP_ITEM( KExtensionAif,   KMimeTypeAiff ),
+    MIME_MAP_ITEM( KExtensionAifc,  KMimeTypeAiff ),
+    MIME_MAP_ITEM( KExtensionAiff,  KMimeTypeAiff ),
+    MIME_MAP_ITEM( KExtensionAmr,   KMimeTypeAmr ),
+    MIME_MAP_ITEM( KExtensionAu,    KMimeTypeAu ), // KMimeTypeAudioBasic?  "audio/x-au"?
+    MIME_MAP_ITEM( KExtensionAwb,   KMimeTypeAwb ),
+    MIME_MAP_ITEM( KExtensionMid,   KMimeTypeMidi ),
+    MIME_MAP_ITEM( KExtensionMidi,  KMimeTypeMidi ),
+    MIME_MAP_ITEM( KExtensionMka,   KMimeTypeMatroska ),
+    MIME_MAP_ITEM( KExtensionMp3,   KMimeTypeMpeg ),
+    MIME_MAP_ITEM( KExtensionOgg,   KMimeTypeOgg ),
+    MIME_MAP_ITEM( KExtensionRa,    KMimeTypeReal ),
+    MIME_MAP_ITEM( KExtensionRam,   KMimeTypeReal ),
+    MIME_MAP_ITEM( KExtensionRmi,   KMimeTypeMid ),
+    MIME_MAP_ITEM( KExtensionSnd,   KMimeTypeBasic ),
+    MIME_MAP_ITEM( KExtensionSpMid, KMimeTypeSpMidi ),
+    MIME_MAP_ITEM( KExtensionWav,   KMimeTypeWav ), // "audio/x-wav"?
+    MIME_MAP_ITEM( KExtensionWma,   KMimeTypeWma )
+};
+
+// ----------------------------------------------------------------------------------------------------------
+// Look for Mime Type from map by file extension
+// Returns NULL if file extension is not known
+// ----------------------------------------------------------------------------------------------------------
+//
+static const TDesC8 * FindMimeTypeFromMap ( const TDesC& aFilename )
+    {
+    // extract extension
+   	TPtrC extension;
+    TInt pos = aFilename.LocateReverseF( '.' );
+    if ( pos < 0  || ++pos >= aFilename.Length() )
+        {
+        return NULL;
+        }
+    extension.Set( aFilename.Mid( pos ) );
+
+    // binary search from Mime Map
+    TUint begin = 0;
+    TUint end = sizeof KMimeMap / sizeof (TMimeMapItem);
+    while (begin < end)
+        {
+        TUint at = (begin + end) / 2;
+        const TMimeMapItem & item = KMimeMap[at];
+        TInt r = item.iExt->CompareF(extension);
+        if (r == 0)
+            {
+            return item.iType;
+            }
+        else if (r > 0)
+            {
+            end = at;
+            }
+        else
+            {
+            begin = at + 1;
+            }
+        }
+    return NULL;
+}
+
+// ============================ MEMBER FUNCTIONS ==============================
+
+// ----------------------------------------------------------------------------------------------------------
+// Set HBufC data member.
+// ----------------------------------------------------------------------------------------------------------
+//
+EXPORT_C TInt MPXDbCommonUtil::SetHBuf(
+    HBufC*& aBuf,
+    const TDesC* aSource,
+    TInt aMaxLen /*= -1*/)
+    {
+    TInt ret( KErrNone );
+    delete aBuf;
+    aBuf = NULL;
+
+    if (aSource)
+        {
+        if (aMaxLen != -1 && aSource->Length() > aMaxLen)
+            {
+            aBuf = aSource->Left(aMaxLen).Alloc();
+            ret = KErrOverflow;
+            }
+        else
+            {
+            aBuf = aSource->Alloc();
+            }
+        }
+    else
+        {
+        aBuf = HBufC::New(0);
+        }
+
+    if (!aBuf)
+        {
+        ret = KErrNoMemory;
+        }
+
+    return ret;
+    }
+
+// ----------------------------------------------------------------------------------------------------------
+// Replace single quotes `'` with two single quotes `''` as text queries are
+// delimited by single quotes
+// also replace 0x00 and '\t' as they will cause crash in SQLite and UI respectively
+// ----------------------------------------------------------------------------------------------------------
+//
+EXPORT_C void MPXDbCommonUtil::FindAndReplaceSingleQuote(const TDesC& aSrc, TDes& aTrg)
+    {
+    TText ch;
+    TInt srcLen(aSrc.Length());
+
+    for (TInt i = 0; i < srcLen; ++i)
+        {
+        ch = aSrc[i];
+        if((ch == 0) || (ch == TText('\t')))
+            {
+            aTrg.Append(TText(' '));
+            }
+        else
+            {
+            aTrg.Append(ch);
+            if (ch == TText('\''))
+                {
+                aTrg.Append(ch);
+                }
+            }
+        }
+    }
+
+// ----------------------------------------------------------------------------------------------------------
+// Delete file from file system
+// ----------------------------------------------------------------------------------------------------------
+//
+EXPORT_C TInt MPXDbCommonUtil::DeleteFile(
+    RFs& aFs,
+    const TDesC& aFile)
+    {
+    TInt ret(KErrNone);
+    if(BaflUtils::FileExists(aFs, aFile))
+        {
+         ret = aFs.Delete(aFile);
+
+        if (ret == KErrAccessDenied)
+            {
+            aFs.SetAtt(aFile,KEntryAttNormal,KEntryAttReadOnly);
+            ret = aFs.Delete(aFile);
+            }
+        }
+    return ret;
+    }
+
+// ----------------------------------------------------------------------------------------------------------
+// Get the drive Id with a given volume unique Id
+// ----------------------------------------------------------------------------------------------------------
+//
+EXPORT_C TInt MPXDbCommonUtil::GetDriveIdMatchVolIdL(
+    RFs& aFs,
+    TUint aVolumeId)
+    {
+    TDriveList driveList;
+    TBool found(EFalse);
+    TInt driveNum(EDriveA);
+
+    User::LeaveIfError(aFs.DriveList(driveList));
+    for (; driveNum <= EDriveZ; ++driveNum)
+        {
+        if (driveList[driveNum])
+            {
+            TVolumeInfo volInfo;
+
+            if ((aFs.Volume(volInfo, driveNum) == KErrNone) &&
+                (volInfo.iUniqueID == aVolumeId))
+                {
+                found = ETrue;
+                break;
+                }
+            }
+        }
+
+    if (!found)
+        {
+        driveNum = KErrNotFound;
+        }
+
+    return driveNum;
+    }
+
+// ----------------------------------------------------------------------------------------------------------
+// Get the volume Id with a given drive Id
+// ----------------------------------------------------------------------------------------------------------
+//
+EXPORT_C TUint MPXDbCommonUtil::GetVolIdMatchDriveIdL(
+    RFs& aFs,
+    TInt aDriveId)
+    {
+    TUint volId (0);
+    TVolumeInfo volInfo;
+    TInt err = aFs.Volume(volInfo, aDriveId);
+    if (err == KErrNone)
+        {
+        volId = volInfo.iUniqueID;
+        }
+    else if (err == KErrNotReady)
+        {
+        volId = 0;
+        }
+    else
+        {
+        User::Leave(err);
+        }
+
+    return volId;
+    }
+
+// ----------------------------------------------------------------------------
+// Generate a 32bits Unique Id with MD5
+// ----------------------------------------------------------------------------
+//
+EXPORT_C TUint32 MPXDbCommonUtil::GenerateUniqueIdL(
+    RFs& aFs,
+    TMPXGeneralCategory aTableId,
+    const TDesC& aName,
+    TBool aCaseSensitive)
+    {
+    MPX_FUNC("MPXDbCommonUtil::GenerateUniqueIdL");
+
+    TInt extractPos(0);
+
+    if( aName.Find(KPathStart) == KMCPathStartWithColon )
+        {
+        // aName is a filename
+        extractPos = KMCPathStartPos;     // c:\..., include first '\' of the path
+        }
+
+    TBuf<KMaxFileName+KMCIntegerLen> fileName;
+    if( extractPos )
+        {
+        // append volume's unique Id to path to maintain uniqueness
+        TDriveUnit driveUnit( aName );
+        TUint volId = MPXDbCommonUtil::GetVolIdMatchDriveIdL(aFs, driveUnit);
+        if( volId )
+            {
+            fileName.AppendNum( volId );
+            }
+        else
+            {
+            // If media/drive doesn't exist, using whole path
+            extractPos = 0;
+            }
+        }
+
+    // append the path part
+    fileName.Append( aName.Mid( extractPos ) );
+
+    if( !aCaseSensitive )
+        {
+        fileName.LowerCase();
+        }
+
+    TInt narrowFileLen(0);
+    TPtrC8 narrowFileName;
+    #if defined(_UNICODE)
+        narrowFileLen = fileName.Length() * 2;
+        narrowFileName.Set((TUint8*)fileName.Ptr(), narrowFileLen);
+    #else
+        narrowFileLen = fileName.Length();
+        narrowFileName.Set(fileName.Ptr(), narrowFileLen);
+    #endif
+
+    CMD5* hasher = CMD5::NewL();
+    CleanupStack::PushL( hasher );
+    hasher->Reset();
+    TBuf8<16> hash( hasher->Hash( narrowFileName ) );   //hashed to 128bits
+    CleanupStack::PopAndDestroy( hasher );
+
+    const TText8* ptr = hash.Ptr();
+
+    TUint32 uniqueId(0);
+    uniqueId = aTableId << 28;
+    uniqueId |= (ptr[3]&0x0F)<<24 | (ptr[2]<<16) | (ptr[1]<<8) | ptr[0];
+    return uniqueId;
+    }
+
+// ---------------------------------------------------------------------------
+// Append an item into the media array
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void MPXDbCommonUtil::AppendMediaL(
+    CMPXMediaArray& aArray,
+    const TDesC& aTitle,
+    TMPXGeneralType aType,
+    TMPXGeneralCategory aCat,
+    TMPXItemId aId,
+    TInt aNonPermissibleActions,
+    TUint aDbflag)
+    {
+    MPX_FUNC("MPXDbCommonUtil::AppendMediaL");
+
+    CMPXMedia* entry = ConstructMediaLC(aTitle, aType, aCat, aId, aNonPermissibleActions, aDbflag);
+    aArray.AppendL(*entry);
+    CleanupStack::PopAndDestroy(entry);
+    }
+
+// ----------------------------------------------------------------------------
+// Append an item into the media array
+// ----------------------------------------------------------------------------
+//
+EXPORT_C void MPXDbCommonUtil::PrependMediaL(
+    CMPXMediaArray& aArray,
+    const TDesC& aTitle,
+    TMPXGeneralType aType,
+    TMPXGeneralCategory aCat,
+    TMPXItemId aId /* = 0 */,
+    TInt aNonPermissibleActions /* = 0 */,
+    TUint aDbflag /* = 0 */,
+    TInt aPos /* = 0 */)
+    {
+    MPX_FUNC("MPXDbCommonUtil::PrependMediaL");
+
+    CMPXMedia* entry = ConstructMediaLC(aTitle, aType, aCat, aId, aNonPermissibleActions, aDbflag);
+    User::LeaveIfError(aArray.Insert(*entry, aPos));
+    CleanupStack::PopAndDestroy(entry);
+    }
+
+// ----------------------------------------------------------------------------
+// Append an item into the media array
+// ----------------------------------------------------------------------------
+//
+EXPORT_C void MPXDbCommonUtil::FillInSupportedUIDsL(
+    const TArray<TMPXAttribute>& aAttrs,
+    RArray<TInt>& aSupportedIds)
+    {
+    MPX_FUNC("MPXDbCommonUtil::FillInSupportedUIDs");
+
+    TInt attrCount(aAttrs.Count());
+    for (TInt i = 0; i < attrCount; ++i)
+        {
+        if (aAttrs[i].ContentId() == KMPXMediaIdGeneral)
+            {
+            aSupportedIds.AppendL(KMPXMediaIdGeneral);
+            }
+        else if (aAttrs[i].ContentId() == KMPXMediaIdMusic)
+            {
+            aSupportedIds.AppendL(KMPXMediaIdMusic);
+            }
+        else if (aAttrs[i].ContentId() == KMPXMediaIdAudio)
+            {
+            aSupportedIds.AppendL(KMPXMediaIdAudio);
+            }
+        else if (aAttrs[i].ContentId() == KMPXMediaIdDrm)
+            {
+            aSupportedIds.AppendL(KMPXMediaIdDrm);
+            }
+        else if (aAttrs[i].ContentId() == KMPXMediaIdCollectionDetails)
+            {
+            aSupportedIds.AppendL(KMPXMediaIdCollectionDetails);
+            }
+        else
+            {
+            // ignore attribute
+            }
+        }
+    }
+
+// ----------------------------------------------------------------------------
+// Fill in change event message with the given info
+// ----------------------------------------------------------------------------
+//
+EXPORT_C void MPXDbCommonUtil::FillItemChangedMessageL(
+    CMPXMessage& aMessage,
+    TMPXItemId aId,
+    TMPXChangeEventType aChangeType,
+    TMPXGeneralCategory aCategory,
+    TUint aUid,
+    TMPXItemId aDeprecatedId)
+    {
+    MPX_FUNC("MPXDbCommonUtil::FillItemChangedMessageL");
+    MPX_DEBUG5("MPXDbCommonUtil::FillItemChangedMessageL: type [%d], category [%d], id[0x%x], oldId[0x%x]",
+               aChangeType, aCategory, aId.iId1, aDeprecatedId.iId1);
+
+    aMessage.SetTObjectValueL<TMPXMessageId>(KMPXMessageGeneralId, KMPXMessageIdItemChanged);
+    aMessage.SetTObjectValueL<TUid>(KMPXMessageCollectionId, TUid::Uid(aUid));
+    aMessage.SetTObjectValueL<TMPXChangeEventType>(KMPXMessageChangeEventType, aChangeType);
+    aMessage.SetTObjectValueL<TMPXGeneralCategory>(KMPXMessageMediaGeneralCategory, aCategory);
+    aMessage.SetTObjectValueL<TMPXItemId>(KMPXMessageMediaGeneralId, aId);
+
+    if ((aDeprecatedId != 0) && (aId != aDeprecatedId))
+        {
+        aMessage.SetTObjectValueL<TMPXItemId>(KMPXMessageMediaDeprecatedId, aDeprecatedId);
+        }
+    }
+
+// ----------------------------------------------------------------------------
+// Add an item changed message to the message array
+// ----------------------------------------------------------------------------
+//
+EXPORT_C void MPXDbCommonUtil::AddItemChangedMessageL(
+    CMPXMessageArray& aMessageArray,
+    TMPXItemId aId,
+    TMPXChangeEventType aChangeType,
+    TMPXGeneralCategory aCategory,
+    TUint aUid,
+    TMPXItemId aDeprecatedId /* = 0 */)
+    {
+    MPX_FUNC("MPXDbCommonUtil::AddItemChangedMessageL");
+    CMPXMessage* message = CMPXMedia::NewL();
+    CleanupStack::PushL(message);
+
+    FillItemChangedMessageL(*message, aId, aChangeType, aCategory, aUid, aDeprecatedId);
+    if (FindItemChangedMessageL(aMessageArray, *message) == KErrNotFound)
+        {
+        aMessageArray.AppendL(*message); // ownership xfer
+        }
+    CleanupStack::PopAndDestroy(message);
+    }
+
+// ----------------------------------------------------------------------------
+// Find the message in the array, if not KErrNotFound is returned; otherwise the
+// index of the first matching message is returned
+// ----------------------------------------------------------------------------
+//
+EXPORT_C TInt MPXDbCommonUtil::FindItemChangedMessageL(
+    const CMPXMessageArray& aMessageArray,
+    const CMPXMessage& aMessage)
+    {
+    MPX_FUNC("MPXDbCommonUtil::FindItemChangedMessageL");
+
+    TInt index(KErrNotFound);
+    TInt messageCount(aMessageArray.Count());
+
+    for (TInt i = 0; i < messageCount; ++i)
+        {
+        CMPXMessage* message = aMessageArray.AtL(i);
+        
+        if (message->IsSupported(KMPXMessageGeneralId) &&
+            message->IsSupported(KMPXMessageCollectionId) &&
+            message->IsSupported(KMPXMessageChangeEventType) &&
+            message->IsSupported(KMPXMessageMediaGeneralCategory) &&
+            message->IsSupported(KMPXMessageMediaGeneralId) &&
+            aMessage.IsSupported(KMPXMessageGeneralId) &&
+            aMessage.IsSupported(KMPXMessageCollectionId) &&
+            aMessage.IsSupported(KMPXMessageChangeEventType) &&
+            aMessage.IsSupported(KMPXMessageMediaGeneralCategory) &&
+            aMessage.IsSupported(KMPXMessageMediaGeneralId))
+            {
+            if (message->ValueTObjectL<TMPXMessageId>(KMPXMessageGeneralId) == aMessage.ValueTObjectL<TMPXMessageId>(KMPXMessageGeneralId) &&
+                message->ValueTObjectL<TUid>(KMPXMessageCollectionId) == aMessage.ValueTObjectL<TUid>(KMPXMessageCollectionId) &&
+                message->ValueTObjectL<TMPXChangeEventType>(KMPXMessageChangeEventType) == aMessage.ValueTObjectL<TMPXChangeEventType>(KMPXMessageChangeEventType) &&
+                message->ValueTObjectL<TMPXGeneralCategory>(KMPXMessageMediaGeneralCategory) == aMessage.ValueTObjectL<TMPXGeneralCategory>(KMPXMessageMediaGeneralCategory) &&
+                message->ValueTObjectL<TMPXItemId>(KMPXMessageMediaGeneralId) == aMessage.ValueTObjectL<TMPXItemId>(KMPXMessageMediaGeneralId))
+                {
+                if (!message->IsSupported(KMPXMessageMediaDeprecatedId) &&
+                    !aMessage.IsSupported(KMPXMessageMediaDeprecatedId))
+                    {
+                    index = i;
+                    break;
+                    }
+                else if (message->IsSupported(KMPXMessageMediaDeprecatedId) &&
+                         aMessage.IsSupported(KMPXMessageMediaDeprecatedId))
+                    {
+                    if (message->ValueTObjectL<TMPXItemId>(KMPXMessageMediaDeprecatedId) ==
+                        aMessage.ValueTObjectL<TMPXItemId>(KMPXMessageMediaDeprecatedId))
+                        {
+                        index = i;
+                        break;
+                       }
+                    }
+                else
+                    {
+                    // else do nothing
+                    }
+                }
+            }
+        }
+
+    return index;
+    }
+
+// ----------------------------------------------------------------------------
+// Get the DRM protection type of the file
+// ----------------------------------------------------------------------------
+//
+EXPORT_C TMCDrmType MPXDbCommonUtil::GetDRMTypeL(const TDesC& aFile)
+    {
+    MPX_FUNC("MPXDbCommonUtil::GetDRMTypeL");
+
+    using namespace ContentAccess;
+    TInt drmProtected(0);
+    TVirtualPathPtr virtualPath(aFile, KDefaultContentObject);
+    CData* content = CData::NewL(virtualPath, EPeek, EContentShareReadOnly);
+    CleanupStack::PushL(content);
+    User::LeaveIfError(content->GetAttribute(EIsProtected, drmProtected));
+    CleanupStack::PopAndDestroy( content );
+    return drmProtected? EMCDrmOmaDrm : EMCDrmNone;
+    }
+
+// ----------------------------------------------------------------------------
+// MPXDbUtil::ProcessSingleQuotesLC
+// ----------------------------------------------------------------------------
+//
+EXPORT_C HBufC* MPXDbCommonUtil::ProcessSingleQuotesLC(
+    const TDesC& aString)
+    {
+    MPX_FUNC("MPXDbCommonUtil::ProcessSingleQuotesLC");
+
+    // reserve space for all single quotes (double the size)
+    HBufC* value = HBufC::NewLC(aString.Length() * 2);
+    TPtr valuePtr(value->Des());
+
+    MPXDbCommonUtil::FindAndReplaceSingleQuote(aString, valuePtr);
+
+    return value;
+    }
+
+// ----------------------------------------------------------------------------
+// MPXDbUtil::ProcessPatternCharsLC
+// 1) a percentage needs to be escaped for sqlite followed by
+//    another percentage sign for escaping % for descriptor formatting, i.e.
+//    % --> %% (this percentage will be treated as a percentage instead of
+//    pattern matching)
+// 2) since back slash is used for escaping the pattern characters, user
+//    specified back slash should be escapped as well, i.e. \ --> \\
+// ----------------------------------------------------------------------------
+//
+EXPORT_C HBufC* MPXDbCommonUtil::ProcessPatternCharsLC(
+    const TDesC& aString)
+    {
+    MPX_FUNC("MPXDbCommonUtil::ProcessPatternCharsLC");
+
+    // reserve space for all percentage signs (triple the size because % should
+    // be replaced by %%)
+    TInt srcLen(aString.Length());
+    HBufC* targetString = HBufC::NewLC(aString.Length() * 3);
+    TPtr targetStringPtr(targetString->Des());
+
+    TPtrC ch;
+    for (TInt i = 0; i < srcLen; ++i)
+        {
+        ch.Set(&aString[i], 1);
+        if (ch.CompareF(KMCPercentage) == 0)
+            {
+            targetStringPtr.Append(KMCPercentage);
+            }
+           else if ( ch.CompareF( KMCBackSlash ) == 0 )
+            {
+            targetStringPtr.Append(KMCBackSlash);
+            }
+        targetStringPtr.Append(ch);            
+        }
+
+    MPX_DEBUG3("    original=%S, new=%S", &aString, targetString);
+    
+    return targetString;
+    }
+
+// ----------------------------------------------------------------------------
+// Constructs an int SQL criterion
+// ----------------------------------------------------------------------------
+//
+EXPORT_C HBufC* MPXDbCommonUtil::SqlCriterionLC(
+    const TDesC& aCriterion,
+    TInt aValue)
+    {
+    MPX_FUNC("MPXDbCommonUtil::SqlCriterionLC");
+
+    HBufC* sqlCriterion = HBufC::NewLC(aCriterion.Length() + KMCIntegerLen);
+    TPtr ptr = sqlCriterion->Des();
+    ptr.Format(aCriterion, aValue);
+    return sqlCriterion;
+    }
+
+// ----------------------------------------------------------------------------
+// Constructs an int64 SQL criterion
+// ----------------------------------------------------------------------------
+//
+EXPORT_C HBufC* MPXDbCommonUtil::SqlCriterion64LC(
+    const TDesC& aCriterion,
+    TInt64 aValue)
+    {
+    MPX_FUNC("MPXDbCommonUtil::SqlCriterion64LC");
+
+    HBufC* sqlCriterion = HBufC::NewLC(aCriterion.Length() + KMCInt64Len);
+    TPtr ptr = sqlCriterion->Des();
+    ptr.Format(aCriterion, aValue);
+    return sqlCriterion;
+    }
+
+// ----------------------------------------------------------------------------
+// Constructs an SQL criterion using two int values
+// ----------------------------------------------------------------------------
+//
+EXPORT_C HBufC* MPXDbCommonUtil::SqlCriterionLC(
+    const TDesC& aCriterion,
+    TInt aValue1,
+    TInt aValue2)
+    {
+    MPX_FUNC("MPXDbCommonUtil::SqlCriterionLC 2");
+
+    HBufC* sqlCriterion = HBufC::NewLC(aCriterion.Length() + 2 * KMCIntegerLen);
+    TPtr ptr = sqlCriterion->Des();
+    ptr.Format(aCriterion, aValue1, aValue2);
+    return sqlCriterion;
+    }
+
+// ----------------------------------------------------------------------------
+// Constructs an SQL criterion using two int64 values
+// ----------------------------------------------------------------------------
+//
+EXPORT_C HBufC* MPXDbCommonUtil::SqlCriterion64LC(
+    const TDesC& aCriterion,
+    TInt64 aValue1,
+    TInt64 aValue2)
+    {
+    MPX_FUNC("MPXDbCommonUtil::SqlCriterion64LC 2");
+
+    HBufC* sqlCriterion = HBufC::NewLC(aCriterion.Length() + 2 * KMCInt64Len);
+    TPtr ptr = sqlCriterion->Des();
+    ptr.Format(aCriterion, aValue1, aValue2);
+    return sqlCriterion;
+    }
+
+// ----------------------------------------------------------------------------
+// Constructs a descriptor SQL criterion
+// ----------------------------------------------------------------------------
+//
+EXPORT_C HBufC* MPXDbCommonUtil::SqlCriterionLC(
+    const TDesC& aCriterion,
+    const TDesC& aValue)
+    {
+    MPX_FUNC("MPXDbCommonUtil::SqlCriterionLC 3");
+
+    HBufC* value = ProcessSingleQuotesLC(aValue);
+
+    HBufC* sqlCriterion = HBufC::NewL(aCriterion.Length() + value->Length());
+    TPtr ptr(sqlCriterion->Des());
+    ptr.Format(aCriterion, value);
+
+    CleanupStack::PopAndDestroy(value);
+    CleanupStack::PushL(sqlCriterion);
+    return sqlCriterion;
+    }
+    
+// ----------------------------------------------------------------------------
+// Constructs a descriptor SQL criterion
+// ----------------------------------------------------------------------------
+//
+EXPORT_C HBufC* MPXDbCommonUtil::SqlCriterionLC(
+    const TDesC& aCriterion,
+    const TDesC& aValue1,
+    const TDesC& aValue2)
+    {
+    MPX_FUNC("MPXDbCommonUtil::SqlCriterionLC 3");
+
+    HBufC* value1 = ProcessSingleQuotesLC(aValue1);
+    HBufC* value2 = ProcessSingleQuotesLC(aValue2);
+
+    HBufC* sqlCriterion = HBufC::NewL(aCriterion.Length() + 
+                                      value1->Length() + 
+                                      value2->Length());
+    TPtr ptr(sqlCriterion->Des());
+    ptr.Format(aCriterion, value1, value2);
+
+    CleanupStack::PopAndDestroy(value2);
+    CleanupStack::PopAndDestroy(value1);
+    CleanupStack::PushL(sqlCriterion);
+    return sqlCriterion;
+    }
+    
+// ----------------------------------------------------------------------------
+// Constructs a descriptor SQL criterion
+// ----------------------------------------------------------------------------
+//
+EXPORT_C HBufC* MPXDbCommonUtil::SqlCriterionLC(
+    const TDesC& aCriterion,
+    const TDesC& aValue1,
+    TInt aValue2,
+    const TDesC& aValue3,
+    TInt aValue4)
+    {
+    MPX_FUNC("MPXDbCommonUtil::SqlCriterionLC 3");
+
+    HBufC* value1 = ProcessSingleQuotesLC(aValue1);
+    HBufC* value3 = ProcessSingleQuotesLC(aValue3);
+
+    HBufC* sqlCriterion = HBufC::NewL(aCriterion.Length() + 
+                                      value1->Length() + 
+                                      value3->Length() + 
+                                      2 * KMCIntegerLen);
+    TPtr ptr(sqlCriterion->Des());
+    ptr.Format(aCriterion, value1, aValue2, value3, aValue4);
+
+    CleanupStack::PopAndDestroy(value3);
+    CleanupStack::PopAndDestroy(value1);
+    CleanupStack::PushL(sqlCriterion);
+    return sqlCriterion;
+    }    
+
+// ----------------------------------------------------------------------------
+// Constructs and adds an int SQL criterion to the criteria array
+// ----------------------------------------------------------------------------
+//
+EXPORT_C TInt MPXDbCommonUtil::AddSqlCriterionL(
+    CDesCArray& aSqlCriteria,
+    const TDesC& aCriterion,
+    TInt aValue)
+    {
+    MPX_FUNC("MPXDbCommonUtil::AddSqlCriterionL");
+
+    HBufC* sqlCriterion = SqlCriterionLC(aCriterion, aValue);
+    TInt length = sqlCriterion->Length();
+    aSqlCriteria.AppendL(*sqlCriterion);
+    CleanupStack::PopAndDestroy(sqlCriterion);
+    return length;
+    }
+
+// ----------------------------------------------------------------------------
+// Constructs and adds a string SQL criterion to the criteria array
+// ----------------------------------------------------------------------------
+//
+EXPORT_C TInt MPXDbCommonUtil::AddSqlCriterionL(
+    CDesCArray& aSqlCriteria,
+    const TDesC& aCriterion,
+    const TDesC& aValue)
+    {
+    MPX_FUNC("MPXDbCommonUtil::AddSqlCriterionL");
+
+    HBufC* sqlCriterion = SqlCriterionLC(aCriterion, aValue);
+    TInt length = sqlCriterion->Length();
+    aSqlCriteria.AppendL(*sqlCriterion);
+    CleanupStack::PopAndDestroy(sqlCriterion);
+    return length;
+    }
+
+
+// ----------------------------------------------------------------------------
+// Create a full path with input drive Id and path
+// ----------------------------------------------------------------------------
+//
+EXPORT_C HBufC* MPXDbCommonUtil::CreateFullPathL(
+    TInt aDriveId,
+    const TDesC& aPath)
+    {
+    MPX_FUNC("MPXDbCommonUtil::CreateFullPathL");
+
+    HBufC* hbuf = HBufC::NewLC(aPath.Length() + KMaxDriveName);
+    TPtr fullPath(hbuf->Des());
+
+    if (aDriveId != KErrNotFound)
+        {
+        TDriveUnit driveUnit(aDriveId);
+        fullPath.Copy(driveUnit.Name());
+        }
+
+    fullPath.Append(aPath);
+    CleanupStack::Pop(hbuf);
+    return hbuf;
+    }
+
+// ----------------------------------------------------------------------------
+// MPXDbCommonUtil::AppendValueL
+// ----------------------------------------------------------------------------
+//
+EXPORT_C void MPXDbCommonUtil::AppendValueL(
+    CDesCArray& aFields,
+    CDesCArray& aValues,
+    const TDesC& aField,
+    const TDesC& aValue)
+    {
+    MPX_FUNC("MPXDbCommonUtil::AppendValueL");
+
+    aFields.AppendL(aField);
+
+    HBufC* value = HBufC::NewLC(aValue.Length() * 2 + 2);
+    TPtr valuePtr(value->Des());
+
+    MPXDbCommonUtil::FindAndReplaceSingleQuote(aValue, valuePtr);
+
+    // use 'value' instead of value, 0 length strings should be ''
+    //
+    if( valuePtr.Length() )
+        {
+        valuePtr.Insert(0, KMCSingleQuote);
+        valuePtr.Append(KMCSingleQuote);
+        }
+    else
+        {
+        valuePtr.Append(KMCSingleQuote);
+        valuePtr.Append(KMCSingleQuote);
+        }
+    aValues.AppendL(valuePtr);
+
+    CleanupStack::PopAndDestroy(value);
+    }
+
+// ----------------------------------------------------------------------------
+// MPXDbCommonUtil::AppendValueL
+// ----------------------------------------------------------------------------
+//
+EXPORT_C void MPXDbCommonUtil::AppendValueL(
+    CDesCArray& aFields,
+    CDesCArray& aValues,
+    const TDesC& aField,
+    TUint32 aValue)
+    {
+    MPX_FUNC("MPXDbCommonUtil::AppendValueL");
+
+    aFields.AppendL(aField);
+    TBuf<KMCIntegerLen> value;
+    value.AppendNum(static_cast<TInt64>(aValue));
+    aValues.AppendL(value);
+    }
+
+// ----------------------------------------------------------------------------
+// Gets the MIME type for a specified URI
+// ----------------------------------------------------------------------------
+//
+EXPORT_C TDataType MPXDbCommonUtil::GetMimeTypeForUriL(
+    const TDesC& aUri)
+    {
+    MPX_FUNC("MPXDbUtil::GetMimeTypeForUriL");
+
+    if ( const TDesC8 * type = FindMimeTypeFromMap (aUri) )
+        {
+        return TDataType(*type);
+        }
+    
+    RApaLsSession appArc;
+    User::LeaveIfError(appArc.Connect());
+    CleanupClosePushL(appArc);
+    TUid dummyUid(KNullUid);
+    TDataType mimeType;
+    appArc.AppForDocument(aUri, dummyUid, mimeType);
+    CleanupStack::PopAndDestroy(&appArc);
+
+    return mimeType;
+    }
+
+// ----------------------------------------------------------------------------
+// MPXDbCommonUtil::StringFromArrayLC
+// ----------------------------------------------------------------------------
+//
+EXPORT_C HBufC* MPXDbCommonUtil::StringFromArrayLC(
+    const CDesCArray& aArray,
+    const TDesC& aSeparator)
+    {
+    MPX_FUNC("MPXDbCommonUtil::StringFromArrayLC");
+
+    HBufC* str(NULL);
+    TInt count(aArray.Count());
+    if (count)
+        {
+        TInt len(0);
+        TInt index(0);
+        for (index = 0; index < count; ++index)
+            {
+            len += aArray[index].Length();
+            }
+
+        str = HBufC::NewLC(len + (aSeparator.Length() * (count - 1)));
+        TPtr ptr(str->Des());
+        TPtrC16 item;
+        for (index = 0; index < count; ++index)
+            {
+            item.Set(aArray[index]);
+            ptr.Append(item);
+            MPX_DEBUG2("aArray[index] %S", &item);
+            if (index < (count - 1))
+                {
+                ptr.Append(aSeparator);
+                }
+            }
+        }
+    else
+        {
+        str = HBufC::NewLC(0);
+        }
+
+    return str;
+    }
+
+// ----------------------------------------------------------------------------
+// MPXDbCommonUtil::StringFromArraysLC
+// ----------------------------------------------------------------------------
+//
+EXPORT_C HBufC* MPXDbCommonUtil::StringFromArraysLC(
+    const CDesCArray& aNameArray,
+    const CDesCArray& aValueArray,
+    const TDesC& aValueSeparator,
+    const TDesC& aEntitySeparator)
+    {
+    MPX_FUNC("MPXDbCommonUtil::StringFromArraysLC");
+
+    // calculate the length of the SET string
+    TInt len(0);
+    TInt index(0);
+    TInt count(aNameArray.Count());
+    for (index = 0; index < count; ++index)
+        {
+        len += aNameArray[index].Length() + aValueArray[index].Length();
+        }
+
+    // construct the result string
+    HBufC* result = HBufC::NewLC(len +
+        ((aValueSeparator.Length() + aEntitySeparator.Length()) * count));
+    TPtr resultPtr(result->Des());
+    for (index = 0; index < count; ++index)
+        {
+        resultPtr.Append(aNameArray[index]);
+        resultPtr.Append(aValueSeparator);
+        resultPtr.Append(aValueArray[index]);
+
+        if (index < count - 1)
+            {
+            resultPtr.Append(aEntitySeparator);
+            }
+        }
+
+    return result;
+    }
+
+// ----------------------------------------------------------------------------
+// MPXDbCommonUtil::TTimeToDesLC
+// Converts a TTime to the internal SQLite format (YYYY-MM-DD HH:MM:SS).
+// ----------------------------------------------------------------------------
+//
+EXPORT_C HBufC* MPXDbCommonUtil::TTimeToDesLC(
+    const TTime& aTime)
+    {
+    MPX_FUNC("MPXDbCommonUtil::TTimeToDesLC");
+
+    HBufC* dateTime;
+    if (aTime == Time::NullTTime())
+        {
+        dateTime = HBufC::NewLC(0);
+        }
+    else
+        {
+        _LIT(KDateTimeFormat, "%04d-%02d-%02d %02d:%02d:%02d");
+        
+        TTime time(0);
+
+        // negative time means BC, but format string will be invalid with our format,
+        // i.e. %04d in KDateTimeFormat when year is -1 will result in "00-1" and
+        // the whole string becomes "00-1-01-01 00:00:00" which will result in error,
+        // so set to 0 in such cases
+        TDateTime dt = aTime>time ? aTime.DateTime() : time.DateTime();
+        TInt dateTimeLen = KDateTimeFormat().Length();
+        dateTime = HBufC::NewLC(dateTimeLen);
+        TPtr dateTimePtr = dateTime->Des();
+        dateTimePtr.Format(KDateTimeFormat,
+                        dt.Year(),
+                        dt.Month() + 1, // zero based
+                        dt.Day() + 1,   // zero based
+                        dt.Hour(),
+                        dt.Minute(),
+                        dt.Second());
+        }
+    return dateTime;
+    }
+
+// ----------------------------------------------------------------------------
+// MPXDbCommonUtil::DesToTTimeL
+// Converts a date time string in the internal SQLite format (YYYY-MM-DD HH:MM:SS)
+// to a TTime. TTime can only parse in the DD-MM-YYYY HH:MM:SS format.
+// ----------------------------------------------------------------------------
+//
+EXPORT_C TTime MPXDbCommonUtil::DesToTTimeL(
+    const TDesC& aDateTime)
+    {
+    MPX_FUNC("MPXDbCommonUtil::DesToTTimeL");
+
+    TTime time(0);
+    if (aDateTime.Length() != 0)
+        {
+        _LIT(KDash, "-");
+        _LIT(KSpace, " ");
+
+        TLocale locale;
+        TDateFormat iDateFormat = locale.DateFormat();
+
+        HBufC* dateTime = HBufC::NewLC(aDateTime.Length());
+        TPtr dateTimePtr = dateTime->Des();
+
+        //as TTime::Parse is locale dependent, check it:
+        if(iDateFormat==EDateEuropean)
+            {
+            dateTimePtr.Append(aDateTime.Mid(8, 2));//day DD
+            dateTimePtr.Append(KDash);
+            dateTimePtr.Append(aDateTime.Mid(5, 2));//month MM
+            dateTimePtr.Append(KDash);
+            dateTimePtr.Append(aDateTime.Left(4));//year YYYY
+            dateTimePtr.Append(KSpace);
+            }
+        else if(iDateFormat==EDateJapanese)
+            {
+            dateTimePtr.Append(aDateTime.Left(4));//year YYYY
+            dateTimePtr.Append(KDash);
+            dateTimePtr.Append(aDateTime.Mid(5, 2));//month MM
+            dateTimePtr.Append(KDash);
+            dateTimePtr.Append(aDateTime.Mid(8, 2));//day DD
+            dateTimePtr.Append(KSpace);
+            }
+        else //iDateFormat==EDateAmerican
+            {
+            dateTimePtr.Append(aDateTime.Mid(5, 2));//month MM
+            dateTimePtr.Append(KDash);
+            dateTimePtr.Append(aDateTime.Mid(8, 2));//day DD
+            dateTimePtr.Append(KDash);
+            dateTimePtr.Append(aDateTime.Left(4));//year YYYY
+            dateTimePtr.Append(KSpace);            
+            }
+
+		    // When colon (:) is set as Date separator in Date and Time setting, 
+		    // colon in Time descriptors is parsed as Date separator. 
+        if ( locale.DateSeparator(1) == ':')
+            {
+            _LIT(KDot, ".");
+        
+        		// time HH.MM.SS
+            dateTimePtr.Append( aDateTime.Mid(11, 2) );
+            dateTimePtr.Append( KDot );
+            dateTimePtr.Append( aDateTime.Mid(14, 2) );
+            dateTimePtr.Append( KDot );
+            dateTimePtr.Append( aDateTime.Mid(17, 2) );
+            }
+        else
+            {
+            dateTimePtr.Append(aDateTime.Right(8));//time HH:MM:SS
+            }
+
+        User::LeaveIfError(time.Parse(dateTimePtr));
+        CleanupStack::PopAndDestroy(dateTime);
+        }
+    else
+        {
+        time = Time::NullTTime();
+        }
+    return time;
+    }
+
+// ----------------------------------------------------------------------------
+// MPXDbCommonUtil::CurrentTimeDesLC
+// ----------------------------------------------------------------------------
+//
+EXPORT_C HBufC* MPXDbCommonUtil::CurrentTimeDesLC()
+    {
+    MPX_FUNC("MPXDbCommonUtil::CurrentTimeDesLC");
+
+    TTime time;
+    time.HomeTime();
+
+    return TTimeToDesLC(time);
+    }
+
+// ----------------------------------------------------------------------------
+// MPXDbCommonUtil::CurrentDateDesLC
+// ----------------------------------------------------------------------------
+//
+EXPORT_C HBufC* MPXDbCommonUtil::CurrentDateDesLC()
+    {
+    MPX_FUNC("MPXDbCommonUtil::CurrentDateDesLC");
+
+    TTime time;
+    time.HomeTime();
+
+    // Round off to the nearest hour
+    TDateTime date(time.DateTime());
+    date.SetMinute(0);
+    date.SetSecond(0);
+    date.SetMicroSecond(0);
+
+    return TTimeToDesLC(TTime(date));
+    }
+
+// ----------------------------------------------------------------------------
+// MPXDbCommonUtil::GetDriveL
+// ----------------------------------------------------------------------------
+//
+EXPORT_C TInt MPXDbCommonUtil::GetDriveL(
+    const TDesC& aUri,
+    TDriveUnit& aDrive)
+    {
+    MPX_FUNC("MPXDbCommonUtil::GetDriveL");
+
+    TInt err(KErrNotFound);
+    TParsePtrC parser(aUri);
+    if (parser.Drive().Length())
+        {
+        aDrive = TDriveUnit(aUri);
+        err = KErrNone;
+        }
+
+    return err;
+    }
+
+// ----------------------------------------------------------------------------
+// MPXDbCommonUtil::AttributeExistsL
+// ----------------------------------------------------------------------------
+//
+EXPORT_C TBool MPXDbCommonUtil::AttributeExists(
+    const TArray<TMPXAttribute>& aAttrs,
+    const TMPXAttribute& aAttribute)
+    {
+    MPX_FUNC("MPXDbCommonUtil::AttributeExists");
+
+    TBool ret(EFalse);
+
+    TUint content(aAttribute.ContentId());
+    TUint attribute(aAttribute.AttributeId());
+
+    TInt count(aAttrs.Count());
+    for (TInt i = 0; i < count; ++i)
+        {
+        if ((aAttrs[i].ContentId() == content) &&
+            (aAttrs[i].AttributeId() & attribute))
+            {
+            ret = ETrue;
+            break;
+            }
+        }
+
+    return ret;
+    }
+
+// ----------------------------------------------------------------------------
+// MPXDbCommonUtil::ConstructMediaLC
+// ----------------------------------------------------------------------------
+//
+CMPXMedia* MPXDbCommonUtil::ConstructMediaLC(
+    const TDesC& aTitle,
+    TMPXGeneralType aType,
+    TMPXGeneralCategory aCat,
+    TMPXItemId aId,
+    TInt aNonPermissibleActions,
+    TUint aDbflag)
+    {
+    MPX_FUNC("MPXDbCommonUtil::ConstructMediaLC");
+
+    RArray<TInt> supportedIds;
+    CleanupClosePushL(supportedIds);
+    supportedIds.AppendL(KMPXMediaIdGeneral);
+    CMPXMedia* entry = CMPXMedia::NewL(supportedIds.Array());
+    CleanupStack::PopAndDestroy(&supportedIds);
+    CleanupStack::PushL(entry);
+    entry->SetTextValueL(KMPXMediaGeneralTitle, aTitle);
+    entry->SetTObjectValueL<TMPXGeneralType>(KMPXMediaGeneralType, aType);
+    entry->SetTObjectValueL<TMPXGeneralCategory>(KMPXMediaGeneralCategory, aCat);
+    entry->SetTObjectValueL<TMPXItemId>(KMPXMediaGeneralId, aId);
+    entry->SetTObjectValueL<TUint>(KMPXMediaGeneralFlags, aDbflag);
+
+    if (aNonPermissibleActions)
+        {
+        // set non-permissible actions
+        entry->SetTObjectValueL<TMPXGeneralNonPermissibleActions>(KMPXMediaGeneralNonPermissibleActions,
+            static_cast<TMPXGeneralNonPermissibleActions>(aNonPermissibleActions));
+        }
+
+    return entry;
+    }
+
+// ----------------------------------------------------------------------------
+// MPXDbCommonUtil::GetColumnTextL
+// ----------------------------------------------------------------------------
+//
+EXPORT_C TPtrC MPXDbCommonUtil::GetColumnTextL(
+	RSqlStatement& aStatement, 
+	TInt aField)
+	{
+    MPX_FUNC("MPXDbCommonUtil::GetColumnTextL");
+    
+    TPtrC text;
+	if (aStatement.ColumnSize(aField))
+		{
+	    text.Set(aStatement.ColumnTextL(aField));
+		}
+	else
+		{
+	    text.Set(KNullDesC);    	        		
+		}	
+
+    return text;
+	}
+
+// ----------------------------------------------------------------------------
+// Add an album item changed message to the message array
+// ----------------------------------------------------------------------------
+//
+EXPORT_C void MPXDbCommonUtil::AddItemAlbumChangedMessageL(
+    CMPXMessageArray& aMessageArray,
+    TMPXItemId aId,
+    TMPXChangeEventType aChangeType,
+    TMPXGeneralCategory aCategory,
+    TUint aUid,
+    TBool aAlbumArt,
+    TMPXItemId aDeprecatedId)
+    {
+    MPX_FUNC("MPXDbCommonUtil::AddItemChangedMessageL");
+    CMPXMessage* message = CMPXMedia::NewL();
+    CleanupStack::PushL(message);
+
+    FillItemChangedMessageL(*message, aId, aChangeType, aCategory, aUid,
+    		aDeprecatedId );
+    if ( aAlbumArt )
+        {
+        message->SetTObjectValueL<TMPXItemId>(KMPXMessageMediaDeprecatedId, aId);
+        }
+    if (FindItemChangedMessageL(aMessageArray, *message) == KErrNotFound)
+        {
+        aMessageArray.AppendL(*message); // ownership xfer
+        }
+    CleanupStack::PopAndDestroy(message);
+    }
+// End of File