mpxplugins/serviceplugins/collectionplugins/mpxsqlitepodcastdbplugin/src/mpxpodcastdbhandler.cpp
branchRCL_3
changeset 53 3de6c4cf6b67
child 66 1f1dad4af8f8
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mpxplugins/serviceplugins/collectionplugins/mpxsqlitepodcastdbplugin/src/mpxpodcastdbhandler.cpp	Wed Sep 01 12:32:02 2010 +0100
@@ -0,0 +1,1616 @@
+/*
+* 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:  This class is used by db plugin to add episodes into DB or
+*                remove episodes from DB
+*
+*/
+
+
+// INCLUDE FILES
+#include <PCRes.rsg>
+#include <bautils.h>
+#include <MetaDataUtility.h>
+#ifdef RD_MULTIPLE_DRIVE
+#include <driveinfo.h>
+#include <pathinfo.h>
+#endif //RD_MULTIPLE_DRIVE
+
+#include <mpxmediageneraldefs.h>
+#include <mpxmediacontainerdefs.h>
+#include <mpxmediamusicdefs.h>
+#include <mpxmediaaudiodefs.h>
+#include <mpxmedia.h>
+#include <mpxmediaarray.h>
+#include <mpxcollectionpath.h>
+#include <mpxlog.h>
+
+#include "mpxdbcommondef.h"
+#include "mpxresource.h"
+#include "mpxdbcommonutil.h"
+
+#include "mpxdbutil.h"
+#include "mpxpodcastcollectiondbdef.h"
+#include "mpxpodcastdbmanager.h"
+#include "mpxdbcategory.h"
+#include "mpxdbauxiliary.h"
+#include "mpxpodcastdbhandler.h"
+#include "mpxpodcastdbpluginqueries.h"
+
+// CONSTANTS
+#if defined (__MTP_PROTOCOL_SUPPORT)
+#include <centralrepository.h>
+
+const TUid KMPXMtpSettings = {0x101FFC53};    // MTP CenRep Key UID
+const TUint32 KMPXMtpSaveDeletedRecordFlag = 0x00000001;      // MTP CenRep Key for Delete contents
+#endif
+const TInt KSqlDbCorrupted = -321;
+
+// ============================ MEMBER FUNCTIONS ==============================
+
+// ----------------------------------------------------------------------------
+// Two-phased constructor.
+// ----------------------------------------------------------------------------
+//
+CMPXPodcastDbHandler* CMPXPodcastDbHandler::NewL(
+    RFs& aFs,
+    CMPXResource& aResource)
+    {
+    MPX_FUNC("CMPXPodcastDbHandler::NewL");
+
+    CMPXPodcastDbHandler* self = CMPXPodcastDbHandler::NewLC(aFs, aResource);
+    CleanupStack::Pop(self);
+    return self;
+    }
+
+// ----------------------------------------------------------------------------
+// Two-phased constructor.
+// ----------------------------------------------------------------------------
+//
+CMPXPodcastDbHandler* CMPXPodcastDbHandler::NewLC(
+    RFs& aFs,
+    CMPXResource& aResource)
+    {
+    MPX_FUNC("CMPXPodcastDbHandler::NewLC");
+
+    CMPXPodcastDbHandler* self = new (ELeave) CMPXPodcastDbHandler(aFs, aResource);
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    return self;
+    }
+
+// ----------------------------------------------------------------------------
+// Destructor
+// ----------------------------------------------------------------------------
+//
+CMPXPodcastDbHandler::~CMPXPodcastDbHandler()
+    {
+    MPX_FUNC("CMPXPodcastDbHandler::~CMPXPodcastDbHandler");
+
+    delete iDbPodcast;
+    delete iDbArtist;
+    delete iDbAlbum;
+    delete iDbGenre;
+    delete iDbComposer;
+    delete iDbAuxiliary;
+    delete iDbManager;
+
+    delete iPodcastPublishDateCat;
+    iPodcastPublishDateIds.Close();
+    iDbDrives.Close();
+    }
+
+// ----------------------------------------------------------------------------
+// C++ default constructor can NOT contain any code, that might leave
+// ----------------------------------------------------------------------------
+//
+CMPXPodcastDbHandler::CMPXPodcastDbHandler(
+    RFs& aFs,
+    CMPXResource& aResource) :
+    iFs(aFs),
+    iResource(aResource)
+    {
+    MPX_FUNC("CMPXPodcastDbHandler::CMPXPodcastDbHandler");
+    }
+
+// ----------------------------------------------------------------------------
+// Symbian 2nd phase constructor can leave.
+// ----------------------------------------------------------------------------
+//
+void CMPXPodcastDbHandler::ConstructL()
+    {
+    MPX_FUNC("CMPXPodcastDbHandler::ConstructL");
+
+    iPodcastPublishDateCat = iResource.ReadMenuArrayL(R_MPX_QTN_NMP_PUBLISH_DATE_ARRAY,
+        iPodcastPublishDateIds);
+    
+    //create db manager
+    iDbManager = CMPXPodcastDbManager::NewL(iFs);
+    CDesCArrayFlat* podcastFolders =
+#ifdef RD_MULTIPLE_DRIVE
+		GetPodcastFoldersL();
+#else
+    	iResource.ReadDesCArrayL(R_MC_DEFAULT_MUSIC_FOLDERS);
+#endif
+
+    // create the podcast folders and initialize iDbDrives
+    CleanupStack::PushL(podcastFolders);
+    ProcessPodcastFoldersL(*podcastFolders);
+    CleanupStack::PopAndDestroy(podcastFolders);
+
+    // create the db infrastructure
+    iDbPodcast = CMPXDbPodcast::NewL(*iDbManager, iResource, *this);
+    iDbArtist = CMPXDbCategory::NewL(*iDbManager, EMPXArtist);
+    iDbAlbum = CMPXDbCategory::NewL(*iDbManager, EMPXAlbum);
+    iDbGenre = CMPXDbCategory::NewL(*iDbManager, EMPXGenre);
+    iDbComposer = CMPXDbCategory::NewL(*iDbManager, EMPXComposer);
+    iDbAuxiliary = CMPXDbAuxiliary::NewL(*iDbManager);
+
+    // make sure all databases are created and valid
+    MPX_TRAPD(err, iDbManager->InitDatabasesL(iDbDrives));
+
+    // If KErrCorrupt is returned, a database file was found to be corrupted
+    // and was replaced with a new one.  The db plugin can ignore this error and continue
+    // because a new db file was successfully created in a subsequent retry.
+    if ((err != KErrNone) && (err != KErrCorrupt) && (err != KErrDiskFull))
+        {
+        // leave to signal the caller that there was an error why creating and opening
+        // one or more of the databases
+        User::Leave(err);
+        }
+    else if (err == KErrDiskFull)
+        {
+        iOutOfDisk = ETrue;
+        }
+    else
+        {
+        // do nothing
+        }
+    // Verify the volume ID Matches
+    MPX_TRAP(err,VerifyVolumeIdL());
+    if ((err != KErrNone) && (err != KErrDiskFull))
+        {
+        // leave to signal the caller that there was an error why creating and opening
+        // one or more of the databases
+        User::Leave(err);
+        }
+    else if (err == KErrDiskFull)
+        {
+        iOutOfDisk = ETrue;
+        }
+
+    // iDbManager->PrintDatabaseL();
+
+    MPX_DEBUG2("CMPXDbHandler::ConstructL DbCount[%d]", iDbManager->DatabaseCount());
+    }
+
+// ----------------------------------------------------------------------------
+// Add episode into collection
+// ----------------------------------------------------------------------------
+//
+TUint32 CMPXPodcastDbHandler::AddEpisodeL(
+    const CMPXMedia& aMedia)
+    {
+    MPX_FUNC("CMPXPodcastDbHandler::AddEpisodeL");
+
+    BeginTransactionL();
+
+    TUint32 episodeId(0);
+    MPX_TRAPD(err, episodeId = DoAddEpisodeL(aMedia));
+
+    if (iOutOfDisk && (err == KErrNotFound))
+        {
+        err = KErrDiskFull;
+        }
+    EndTransactionL(err);
+
+    return episodeId;
+    }
+
+// ----------------------------------------------------------------------------
+// Update a episode in the collection
+// ----------------------------------------------------------------------------
+//
+CMPXDbActiveTask::TChangeVisibility CMPXPodcastDbHandler::UpdateEpisodeL(
+    const CMPXMedia& aMedia,
+    CMPXMessageArray& aItemChangedMessages)
+    {
+    MPX_FUNC("CMPXPodcastDbHandler::UpdateEpisodeL");
+
+    BeginTransactionL();
+    CMPXDbActiveTask::TChangeVisibility visibleChange(CMPXDbActiveTask::ENotVisibile);
+    MPX_TRAPD(err, visibleChange = DoUpdateEpisodeL(aMedia, aItemChangedMessages));
+    EndTransactionL(err);
+    return visibleChange;
+    }
+
+// ----------------------------------------------------------------------------
+// Remove the entire podcast collection database
+// ----------------------------------------------------------------------------
+//
+void CMPXPodcastDbHandler::RemoveEntireCollectionL()
+    {
+    MPX_FUNC("CMPXPodcastDbHandler::RemoveEntireCollectionL");
+
+    BeginTransactionL();
+    MPX_TRAPD(err, iDbManager->RecreateAllDatabasesL());
+    EndTransactionL(err);
+    }
+
+// ----------------------------------------------------------------------------
+// Delete a episode from collection
+// The function notifies collection model to perform deletion
+// ----------------------------------------------------------------------------
+//
+void CMPXPodcastDbHandler::RemoveEpisodeL(
+    TUint32 aEpisodeId,
+    CDesCArray& aUriArray,
+    CMPXMessageArray& aItemChangedMessages,
+    TBool aDeleteRecord)
+    {
+    MPX_FUNC("CMPXPodcastDbHandler::RemoveEpisodeL");
+
+    BeginTransactionL();
+    MPX_TRAPD(err, DoRemoveEpisodeL(aEpisodeId, aUriArray, aItemChangedMessages, aDeleteRecord));
+    EndTransactionL(err);
+    }
+
+// ----------------------------------------------------------------------------
+// Removes a category of episodes from the podcast collection, and its
+// corresponding category in the lookup table
+// ----------------------------------------------------------------------------
+//
+void CMPXPodcastDbHandler::RemoveEpisodesMatchingCategoryL(
+    TMPXGeneralCategory aCategory,
+    TUint32 aCategoryId,
+    CDesCArray& aUriArray,
+    CMPXMessageArray& aItemChangedMessages)
+    {
+    MPX_FUNC("CMPXPodcastDbHandler::RemoveEpisodesMatchingCategoryL");
+
+    BeginTransactionL();
+    MPX_TRAPD(err, DoRemoveEpisodesMatchingCategoryL(aCategory, aCategoryId,
+        aUriArray, aItemChangedMessages));
+    EndTransactionL(err);
+    }
+
+// ----------------------------------------------------------------------------
+// Delete episode(s) from collection belonging to specified publish date category
+// The function notifies collection model to perform deletion
+// ----------------------------------------------------------------------------
+//
+void CMPXPodcastDbHandler::RemoveEpisodesMatchingPublishDateCategoryL(
+    TUint32 aCategoryId,
+    CDesCArray& aUriArray,
+    CMPXMessageArray& aItemChangedMessages)
+    {
+    MPX_FUNC("CMPXPodcastDbHandler::RemoveEpisodesMatchingPublishDateCategoryL");
+
+    BeginTransactionL();
+    MPX_TRAPD(err, DoRemoveEpisodesMatchingPublishDateCategoryL(aCategoryId,
+        aUriArray, aItemChangedMessages));
+    EndTransactionL(err);
+    }
+
+// ----------------------------------------------------------------------------
+// Cleanup records marked as deleted. This is designated for MTP to clean up
+// records marked as deleted at the end of its session.
+// ----------------------------------------------------------------------------
+//
+void CMPXPodcastDbHandler::CleanupDeletedRecordsL()
+    {
+    MPX_FUNC("CMPXPodcastDbHandler::CleanupDeletedRecordsL");
+
+    BeginTransactionL();
+    MPX_TRAPD(err, DoCleanupDeletedRecordsL());
+    EndTransactionL(err);
+    }
+
+// ----------------------------------------------------------------------------
+//  Read all episodes and cache them into an array ordered by episode name
+// ----------------------------------------------------------------------------
+//
+void CMPXPodcastDbHandler::GetAllEpisodesL(
+    const TArray<TMPXAttribute>& aAttrs,
+    CMPXMediaArray& aMediaArray)
+    {
+    MPX_FUNC("CMPXPodcastDbHandler::GetAllEpisodesL");
+    iDbPodcast->GetAllEpisodesL(aAttrs, aMediaArray);
+    }
+
+// ----------------------------------------------------------------------------
+// Retrieve the episode(s) with the specified title
+// ----------------------------------------------------------------------------
+//
+void CMPXPodcastDbHandler::GetEpisodesMatchingTitleL(
+    TUint aTitleId,
+    const TArray<TMPXAttribute>& aAttrs,
+    CMPXMediaArray& aMediaArray)
+    {
+    MPX_FUNC("CMPXPodcastDbHandler::GetEpisodesMatchingTitleL");
+    iDbPodcast->GetEpisodesForCategoryL(EMPXAlbum, aTitleId, aAttrs,
+                                        aMediaArray, ETrue);
+    }
+
+// ----------------------------------------------------------------------------
+// Retrieve the episode(s) belonging to the specified playlist
+// ----------------------------------------------------------------------------
+//
+void CMPXPodcastDbHandler::GetEpisodesMatchingPlaylistL(
+    TUint aPlaylistId,
+    const TArray<TMPXAttribute>& aAttrs,
+    CMPXMediaArray& aMediaArray,
+    TInt& aIndexOfCurrentlyPlayingItem)
+    {
+    MPX_FUNC("CMPXPodcastDbHandler::GetEpisodesMatchingPlaylistL");
+
+    switch (aPlaylistId)
+        {
+        case KRecentlyAddedPlaylistUID:
+            {
+            iDbPodcast->GetRecentlyAddedPlaylistEpisodesL(aAttrs, aMediaArray,
+                aIndexOfCurrentlyPlayingItem);
+            break;
+            }
+        case KNotPlayedPlaylistUID:
+            {
+            iDbPodcast->GetNotYetPlayedPlaylistEpisodesL(aAttrs, aMediaArray,
+                aIndexOfCurrentlyPlayingItem);
+            break;
+            }
+        default:
+            {
+            User::Leave(KErrNotSupported);
+            }
+        }
+    }
+
+// ----------------------------------------------------------------------------
+// Retrieve the episode with the specified ID
+// ----------------------------------------------------------------------------
+//
+void CMPXPodcastDbHandler::GetEpisodeL(
+    TUint32 aEpisodeId,
+    const TArray<TMPXAttribute>& aAttrs,
+    CMPXMediaArray& aMediaArray)
+    {
+    MPX_FUNC("CMPXPodcastDbHandler::GetEpisodeL");
+
+    CMPXMedia* media = CMPXMedia::NewL();
+    CleanupStack::PushL(media);
+
+    GetEpisodeL(aEpisodeId, aAttrs, *media);
+    aMediaArray.AppendL(*media);
+
+    CleanupStack::PopAndDestroy(media);
+    }
+
+// ----------------------------------------------------------------------------
+// Retrieve the episode with the specified ID
+// ----------------------------------------------------------------------------
+//
+void CMPXPodcastDbHandler::GetEpisodeL(
+    TUint32 aEpisodeId,
+    const TArray<TMPXAttribute>& aAttrs,
+    CMPXMedia& aMedia)
+    {
+    MPX_FUNC("CMPXPodcastDbHandler::GetEpisodeL");
+    iDbPodcast->GetEpisodeL(aEpisodeId, aAttrs, aMedia);
+    }
+
+// ----------------------------------------------------------------------------
+// Retrieve the episode with the specified URI
+// ----------------------------------------------------------------------------
+//
+TUint32 CMPXPodcastDbHandler::GetEpisodeIdMatchingUriL(
+    const TDesC& aUri)
+    {
+    MPX_FUNC("CMPXPodcastDbHandler::GetEpisodeIdMatchingUriL");
+    return MPXDbCommonUtil::GenerateUniqueIdL(iFs, EMPXCollection, aUri, EFalse);
+    }
+
+// ----------------------------------------------------------------------------
+// Return all podcast title names
+// ----------------------------------------------------------------------------
+//
+void CMPXPodcastDbHandler::GetAllPodcastTitlesL(
+    const TArray<TMPXAttribute>& aAttrs,
+    CMPXMediaArray& aMediaArray)
+    {
+    MPX_FUNC("CMPXPodcastDbHandler::GetAllPodcastTitlesL");
+    iDbAlbum->GetAllCategoryItemsL(aAttrs, aMediaArray);
+    }
+
+// ----------------------------------------------------------------------------
+// Retrieve episodes matching the specified publish playlist id
+// ----------------------------------------------------------------------------
+//
+TInt CMPXPodcastDbHandler::GetEpisodesMatchingPublishPlaylistL(
+    TUint aPlaylistId,
+    const TArray<TMPXAttribute>& aAttrs,
+    TBool aPendingCategoryDeletionFlag,
+    CMPXMediaArray& aMediaArray)
+    {
+    MPX_FUNC("CMPXPodcastDbHandler::GetEpisodesMatchingPublishPlaylistL");
+
+    TInt numEpisodes(0);
+    TMPXItemId podcastPublishDateCatId = 0;
+
+    // the deletion helper is retrieving all the media within this category
+    // to delete it so need to record category id within last item so
+    // that the HandleChangeL callback can cause OpenL to be called after the
+    // last item within the category is deleted
+    if (aPendingCategoryDeletionFlag)
+        {
+        TInt categoryID(EMPXOther);
+
+        // pass in the category Id so that the helper method can add
+        // the category Id to the last item in this category to aid
+        // in deletion of a category
+        podcastPublishDateCatId = (aPlaylistId - KPublishTodayPlaylistUID) | (categoryID << 28);
+        }
+
+    switch (aPlaylistId)
+        {
+        case KPublishAllPlaylistUID:
+            {
+            TInt itemCount(iPodcastPublishDateCat->Count());
+            for (TInt i = 0; i < itemCount; ++i)
+                {
+                TMPXItemId itemId = iPodcastPublishDateIds[i];
+                TInt count(0);
+
+                switch (iPodcastPublishDateIds[i] + KPublishTodayPlaylistUID)
+                    {
+                    case KPublishTodayPlaylistUID:
+                        count = iDbPodcast->GetTodayEpisodesCountL();
+                        break;
+                    case KPublishYesterdayPlaylistUID:
+                        count = iDbPodcast->GetYesterdayEpisodesCountL();
+                        break;
+                    case KPublishThisWeekPlaylistUID:
+                        count = iDbPodcast->GetThisWeekEpisodesCountL();
+                        break;
+                    case KPublishLastWeekPlaylistUID:
+                        count = iDbPodcast->GetLastWeekEpisodesCountL();
+                        break;
+                    case KPublish2WeeksAgoPlaylistUID:
+                        count = iDbPodcast->Get2WeeksAgoEpisodesCountL();
+                        break;
+                    case KPublish3WeeksAgoPlaylistUID:
+                        count = iDbPodcast->Get3WeeksAgoEpisodesCountL();
+                        break;
+                    case KPublishLastMonthPlaylistUID:
+                        count = iDbPodcast->GetLastMonthEpisodesCountL();
+                        break;
+                    case KPublishEarlierPlaylistUID:
+                        count = iDbPodcast->GetEarlierEpisodesCountL();
+                        break;
+                    case KPublishUnknownPlaylistUID:
+                        count = iDbPodcast->GetUnknownEpisodesCountL();
+                        break;
+                    default:
+                        User::Leave(KErrNotFound);
+                        break;
+                    };
+
+                if (count > 0)
+                    {
+                    numEpisodes += count;
+                    MPXDbUtil::AppendMediaL(aMediaArray, iPodcastPublishDateCat->MdcaPoint(i),
+                        EMPXGroup, EMPXPlaylist, EMPXPodcastGroup, EMPXPubDate, itemId);
+                    }
+                }
+            break;
+            }
+
+        case KPublishTodayPlaylistUID:
+            MPX_DEBUG1 (_L("CMPXPodcastDbHandler::GetEpisodesMatchingPublishPlaylistL: Published Today"));
+            iDbPodcast->GetTodayEpisodesL(podcastPublishDateCatId, aAttrs, aMediaArray);
+            break;
+
+        case KPublishYesterdayPlaylistUID:
+            MPX_DEBUG1 (_L("CMPXPodcastDbHandler::GetEpisodesMatchingPublishPlaylistL: Published Yesterday"));
+            iDbPodcast->GetYesterdayEpisodesL(podcastPublishDateCatId, aAttrs, aMediaArray);
+            break;
+
+        case KPublishThisWeekPlaylistUID:
+            MPX_DEBUG1 (_L("CMPXPodcastDbHandler::GetEpisodesMatchingPublishPlaylistL: Published This Week"));
+            iDbPodcast->GetThisWeekEpisodesL(podcastPublishDateCatId, aAttrs, aMediaArray);
+            break;
+
+        case KPublishLastWeekPlaylistUID:
+            MPX_DEBUG1 (_L("CMPXPodcastDbHandler::GetEpisodesMatchingPublishPlaylistL: Published Last Week"));
+            iDbPodcast->GetLastWeekEpisodesL(podcastPublishDateCatId, aAttrs, aMediaArray);
+            break;
+
+        case KPublish2WeeksAgoPlaylistUID:
+            MPX_DEBUG1 (_L("CMPXPodcastDbHandler::GetEpisodesMatchingPublishPlaylistL: Published 2 Weeks Ago"));
+            iDbPodcast->Get2WeeksAgoEpisodesL(podcastPublishDateCatId, aAttrs, aMediaArray);
+            break;
+
+        case KPublish3WeeksAgoPlaylistUID:
+            MPX_DEBUG1 (_L("CMPXPodcastDbHandler::GetEpisodesMatchingPublishPlaylistL: Published 3 Weeks Ago"));
+            iDbPodcast->Get3WeeksAgoEpisodesL(podcastPublishDateCatId, aAttrs, aMediaArray);
+            break;
+
+        case KPublishLastMonthPlaylistUID:
+            MPX_DEBUG1 (_L("CMPXPodcastDbHandler::GetEpisodesMatchingPublishPlaylistL: Published Last Month"));
+            iDbPodcast->GetLastMonthEpisodesL(podcastPublishDateCatId, aAttrs, aMediaArray);
+            break;
+
+        case KPublishEarlierPlaylistUID:
+            MPX_DEBUG1 (_L("CMPXPodcastDbHandler::GetEpisodesMatchingPublishPlaylistL: Published Earlier"));
+            iDbPodcast->GetEarlierEpisodesL(podcastPublishDateCatId, aAttrs, aMediaArray);
+            break;
+
+        case KPublishUnknownPlaylistUID:
+            MPX_DEBUG1 (_L("CMPXPodcastDbHandler::GetEpisodesMatchingPublishPlaylistL: Published Unknown"));
+            iDbPodcast->GetUnknownEpisodesL(podcastPublishDateCatId, aAttrs, aMediaArray);
+            break;
+
+        default:
+            MPX_DEBUG2 (_L("CMPXPodcastDbHandler::GetEpisodesMatchingPublishPlaylistL: Invalid publish ID [%d]"), aPlaylistId);
+            User::Leave(KErrNotFound);
+            break;
+        }
+
+    if (aPlaylistId != KPublishAllPlaylistUID)
+        {
+        numEpisodes = aMediaArray.Count();
+        }
+
+    return numEpisodes;
+    }
+
+// ----------------------------------------------------------------------------
+// Get the name of the row matching the given ID
+// ----------------------------------------------------------------------------
+//
+HBufC* CMPXPodcastDbHandler::GetTitleNameMatchingIdL(
+    const TUint32 aId)
+    {
+    MPX_FUNC("CMPXPodcastDbHandler::GetTitleNameMatchingIdL");
+    return iDbAlbum->GetNameL(aId);
+    }
+
+// ----------------------------------------------------------------------------
+// Get the URI of the row matching the given ID
+// ----------------------------------------------------------------------------
+//
+HBufC* CMPXPodcastDbHandler::GetUriMatchingIdL(
+    const TUint32 aId)
+    {
+    MPX_FUNC("CMPXPodcastDbHandler::GetUriMatchingIdL");
+
+    return iDbPodcast->GetUriL(aId);
+    }
+
+// ----------------------------------------------------------------------------
+// Find episode(s) that satisfy the specified criteria
+// ----------------------------------------------------------------------------
+//
+CMPXMedia* CMPXPodcastDbHandler::FindAllLC(
+    const CMPXMedia& aCriteria,
+    const TArray<TMPXAttribute>& aAttrs)
+    {
+    MPX_FUNC("CMPXPodcastDbHandler::FindAllLC");
+
+    // leave if the given media doesn't contain the following attributes
+    if (!aCriteria.IsSupported(KMPXMediaGeneralType) ||
+        !aCriteria.IsSupported(KMPXMediaGeneralCategory))
+        {
+        User::Leave(KErrArgument);
+        }
+
+    RArray<TInt> supportedIds;
+    CleanupClosePushL(supportedIds);
+    supportedIds.AppendL(KMPXMediaIdContainer);
+    MPXDbCommonUtil::FillInSupportedUIDsL(aAttrs, supportedIds);
+
+    CMPXMedia* entries = CMPXMedia::NewL(supportedIds.Array());
+    CleanupStack::PopAndDestroy(&supportedIds);
+    CleanupStack::PushL(entries);
+
+    CMPXMediaArray* array = CMPXMediaArray::NewL();
+    CleanupStack::PushL(array);
+
+    FindAllL(aCriteria, aAttrs, *array);
+
+    entries->SetTObjectValueL(KMPXMediaGeneralType, EMPXGroup);
+    entries->SetTObjectValueL(KMPXMediaGeneralCategory,
+         aCriteria.ValueTObjectL<TMPXGeneralCategory>(KMPXMediaGeneralCategory));
+    entries->SetCObjectValueL(KMPXMediaArrayContents, array);
+    entries->SetTObjectValueL(KMPXMediaArrayCount, array->Count());
+
+    CleanupStack::PopAndDestroy(array);
+    return entries;
+    }
+
+// ----------------------------------------------------------------------------
+// Find the number of items in the database
+// ----------------------------------------------------------------------------
+//
+TInt CMPXPodcastDbHandler::NumberOfItemsL(
+    TMPXPodcastCategory aCategory)
+    {
+    MPX_FUNC("CMPXPodcastDbHandler::NumberOfItemsL");
+
+    TInt numOfItems(0);
+
+    switch(aCategory)
+        {
+        case EMPXAll:
+        case EMPXEpisode:
+            {
+            numOfItems = iDbPodcast->CountL();
+            break;
+            }
+        case EMPXRecentlyAdded:
+            {
+            numOfItems = iDbPodcast->GetRecentlyAddedEpisodesCountL();
+            break;
+            }
+        case EMPXNotYetPlayed:
+            {
+            numOfItems = iDbPodcast->GetNotYetPlayedEpisodesCountL();
+            break;
+            }
+        case EMPXTitle:
+            {
+            numOfItems = iDbPodcast->GetNotYetPlayedEpisodesCountL();
+            break;
+            }
+        default:
+            {
+            User::Leave(KErrNotSupported);
+            }
+        }
+
+    return numOfItems;
+    }
+
+// ----------------------------------------------------------------------------
+// Has the database been created?
+// ----------------------------------------------------------------------------
+//
+TBool CMPXPodcastDbHandler::DatabaseCreated()
+    {
+    MPX_FUNC("CMPXPodcastDbHandler::DatabaseCreated");
+
+    TBool AuxilaryDbIsRefreshed(EFalse);
+    TRAP_IGNORE(AuxilaryDbIsRefreshed = iDbAuxiliary->IsRefreshedL());
+    // If none of the databases were available, ie out of disk
+    // we return EFalse
+    return iDbManager->IsInitialized() && AuxilaryDbIsRefreshed;
+    }
+
+// ----------------------------------------------------------------------------
+//  CMPXPodcastDbHandler::GetAllEpisodesDurationL
+// ----------------------------------------------------------------------------
+//
+TInt CMPXPodcastDbHandler::GetAllEpisodesDurationL()
+    {
+    MPX_FUNC("CMPXPodcastDbHandler::GetAllEpisodesDurationL");
+    return iDbPodcast->AllEpisodesDurationL();
+    }
+
+// ----------------------------------------------------------------------------
+//  CMPXPodcastDbHandler::GetTitleDurationL
+// ----------------------------------------------------------------------------
+//
+TInt CMPXPodcastDbHandler::GetTitleDurationL(
+    TUint32 aTitleId)
+    {
+    MPX_FUNC("CMPXPodcastDbHandler::GetTitleDurationL");
+    return iDbPodcast->TitleDurationL(aTitleId);
+    }
+
+// ----------------------------------------------------------------------------
+//  CMPXPodcastDbHandler::GetNotPlayedDurationL
+// ----------------------------------------------------------------------------
+//
+TInt CMPXPodcastDbHandler::GetNotPlayedDurationL()
+    {
+    MPX_FUNC("CMPXPodcastDbHandler::GetNotPlayedDurationL");
+    return iDbPodcast->NotPlayedDurationL();
+    }
+
+// ----------------------------------------------------------------------------
+//  CMPXPodcastDbHandler::GetRecentlyAddedDurationL
+// ----------------------------------------------------------------------------
+//
+TInt CMPXPodcastDbHandler::GetRecentlyAddedDurationL()
+    {
+    MPX_FUNC("CMPXPodcastDbHandler::GetRecentlyAddedDurationL");
+    return iDbPodcast->RecentlyAddedDurationL();
+    }
+
+// ----------------------------------------------------------------------------
+// Set the last refreshed time into the collection
+// ----------------------------------------------------------------------------
+//
+void CMPXPodcastDbHandler::SetLastRefreshedTimeL(
+    TTime aTime)
+    {
+    MPX_FUNC("CMPXPodcastDbHandler::SetLastRefreshedTimeL");
+
+    BeginTransactionL();
+    MPX_TRAPD(err, iDbAuxiliary->SetLastRefreshedTimeL(aTime));
+    EndTransactionL(err);
+    }
+
+// ----------------------------------------------------------------------------
+// Get the last refreshed time into the collection
+// ----------------------------------------------------------------------------
+//
+TTime CMPXPodcastDbHandler::GetLastRefreshedTimeL()
+    {
+    MPX_FUNC("CMPXPodcastDbHandler::GetLastRefreshedTimeL");
+    return iDbAuxiliary->LastRefreshedTimeL();
+    }
+
+// ----------------------------------------------------------------------------
+// Set the db corrupted state for all drives
+// ----------------------------------------------------------------------------
+//
+void CMPXPodcastDbHandler::SetDBCorruptedL(
+    TBool aCorrupted)
+    {
+    MPX_FUNC("CMPXPodcastDbHandler::SetDBCorruptedL");
+
+    BeginTransactionL();
+    MPX_TRAPD(err, iDbAuxiliary->SetDBCorruptedL(aCorrupted));
+    EndTransactionL(err);
+    }
+
+// ----------------------------------------------------------------------------
+// Gets the db corrupted state for all drives
+// ----------------------------------------------------------------------------
+//
+TBool CMPXPodcastDbHandler::IsDBCorruptedL()
+    {
+    MPX_FUNC("CMPXPodcastDbHandler::IsDBCorruptedL");
+    return iDbAuxiliary->DBCorruptedL();
+    }
+
+// ----------------------------------------------------------------------------
+// Opens a database
+// ----------------------------------------------------------------------------
+//
+void CMPXPodcastDbHandler::OpenDatabaseL(
+    TInt aDrive)
+    {
+    MPX_FUNC("CMPXPodcastDbHandler::OpenDatabaseL");
+    iDbManager->OpenDatabaseL(aDrive);
+
+    // Verify the volume ID after a remount event
+    VerifyVolumeIdL( aDrive );
+    }
+
+// ----------------------------------------------------------------------------
+// Close a database
+// ----------------------------------------------------------------------------
+//
+void CMPXPodcastDbHandler::CloseDatabaseL(
+    TInt aDrive)
+    {
+    MPX_FUNC("CMPXPodcastDbHandler::CloseDatabaseL");
+    iDbManager->CloseDatabaseL(aDrive);
+    }
+
+// ----------------------------------------------------------------------------
+// Re-create all databases
+// ----------------------------------------------------------------------------
+//
+void CMPXPodcastDbHandler::ReCreateDatabasesL()
+    {
+    MPX_FUNC("CMPXPodcastDbHandler::ReCreateDatabasesL");
+    iDbManager->RecreateAllDatabasesL();
+    }
+
+// ----------------------------------------------------------------------------
+// Set handler refresh status
+// ----------------------------------------------------------------------------
+//
+void CMPXPodcastDbHandler::RefreshStartL()
+    {
+    MPX_FUNC("CMPXPodcastDbHandler::RefreshStartL");
+
+    iOutOfDisk = EFalse;
+    // Re-open databases
+    // This is needed for the case where we were OOD before, but user
+    // has cleared some space but now try to refresh
+    MPX_TRAPD(err, iDbManager->InitDatabasesL(iDbDrives));
+
+    if(err == KErrDiskFull)
+        {
+        iOutOfDisk = ETrue;
+        }
+
+    if(!iOutOfDisk)
+    {
+        MPX_TRAP(err,CheckDiskSpaceOnDrivesL());
+
+        if(err == KErrDiskFull)
+            {
+            iOutOfDisk = ETrue;
+            }
+    }
+    BeginTransactionL();
+    }
+
+// ----------------------------------------------------------------------------
+// Re-set handler refresh status
+// ----------------------------------------------------------------------------
+//
+void CMPXPodcastDbHandler::RefreshEndL()
+    {
+    MPX_FUNC("CMPXPodcastDbHandler::RefreshEndL");
+
+    EndTransactionL(KErrNone);
+
+    if (!iOutOfDisk)
+        {
+        // Write last refreshed time as current time
+        // This also sets corrupt = 0
+        TTime curTime;
+        curTime.HomeTime();
+        SetLastRefreshedTimeL(curTime);
+//        iDbManager->PrintDatabaseL();    // PREQ2536 the files sqlrowsetutil.h and sqlrowsetutil.cpp has been removed
+        }
+    }
+
+// ----------------------------------------------------------------------------
+// CMPXPodcastDbHandler::SetIsPlayingL
+// ----------------------------------------------------------------------------
+//
+void CMPXPodcastDbHandler::SetIsPlayingL(
+    const CMPXMedia& aMedia,
+    TBool aIsPlaying)
+    {
+    MPX_FUNC("CMPXPodcastDbHandler::SetIsPlayingL");
+
+    TUint32 episodeId(0);
+    if (aMedia.IsSupported(KMPXMediaGeneralId))
+        {
+        episodeId = aMedia.ValueTObjectL<TMPXItemId>(KMPXMediaGeneralId);
+        }
+    else if (aMedia.IsSupported(KMPXMediaGeneralUri))
+        {
+        const TDesC& location(aMedia.ValueText(KMPXMediaGeneralUri));
+        episodeId = MPXDbCommonUtil::GenerateUniqueIdL(iFs, EMPXCollection, location, EFalse);
+        }
+    else
+        {
+        User::Leave(KErrArgument);
+        }
+
+    BeginTransactionL();
+    MPX_TRAPD(err, iDbPodcast->SetIsPlayingL(episodeId, aIsPlaying));
+    EndTransactionL(err);
+    }
+
+// ----------------------------------------------------------------------------
+// Get all records count for podcasts
+// ----------------------------------------------------------------------------
+//
+TUint CMPXPodcastDbHandler::GetTotalCountL(TInt aDrive)
+    {
+    MPX_FUNC("CMPXPodcastDbHandler::GetTotalCountL");
+    TUint total(0);
+
+    total = iDbPodcast->GetDrivePodcastCountL(aDrive);
+
+    return total;
+    }
+
+// ----------------------------------------------------------------------------
+// Get all records count for podcasts
+// ----------------------------------------------------------------------------
+//
+void CMPXPodcastDbHandler::GetPodcastUriArrayL(TInt aDrive, TInt aFromID, TInt aRecords,
+                                               CDesCArray& aUriArr, TInt& aLastID)
+    {
+    MPX_FUNC("CMPXPodcastDbHandler::GetTotalUriArrayL");
+
+    iDbPodcast->GetPodcastUriArrayL(aDrive,aFromID,aRecords,aUriArr,aLastID);
+    }
+
+// ----------------------------------------------------------------------------
+// CMPXPodcastDbHandler::DoCleanupDeletedRecordsL
+// ----------------------------------------------------------------------------
+//
+void CMPXPodcastDbHandler::DoCleanupDeletedRecordsL()
+    {
+    MPX_FUNC("CMPXPodcastDbHandler::DoCleanupDeletedRecordsL");
+
+    // delete all marked records from the Music table
+    iDbPodcast->CleanupL();
+
+    // reset the count in the Auxiliary table
+    iDbAuxiliary->SetSaveDeletedRecordCountL(KDbManagerAllDrives,0);
+    }
+
+// ----------------------------------------------------------------------------
+// FindAllL helper
+// ----------------------------------------------------------------------------
+//
+void CMPXPodcastDbHandler::FindAllL(
+    const CMPXMedia& aCriteria,
+    const TArray<TMPXAttribute>& aAttrs,
+    CMPXMediaArray& aMediaArray)
+    {
+    MPX_FUNC("CMPXPodcastDbHandler::FindAllL");
+
+    RArray<TMPXAttribute> attributes;
+    CleanupClosePushL (attributes);
+    MPXUser::MergeAttributeL(aAttrs, attributes);
+
+    // TODO: b10liu: update all users to properly use podcast category?
+    // Some users of FindAll still call without specifying a podcast category group(ie.. delete helper)
+    // so need to check and use media category instead if not available.
+    if (!aCriteria.IsSupported(KMPXMediaPodcastCategoryGroup))
+        {
+        if (!aCriteria.IsSupported(KMPXMediaGeneralCategory))
+            {
+            User::Leave(KErrArgument);
+            }
+        TMPXGeneralCategory category = aCriteria.ValueTObjectL<TMPXGeneralCategory>(KMPXMediaGeneralCategory);
+
+        switch (category)
+            {
+            case EMPXAlbum:
+                {
+                if (!aCriteria.IsSupported(KMPXMediaGeneralId))
+                    {
+                    User::Leave(KErrArgument);
+                    }
+                // return all episodes within this title
+                TMPXItemId episodeTitleId = aCriteria.ValueTObjectL<TMPXItemId>(KMPXMediaGeneralId);
+                GetEpisodesMatchingTitleL(episodeTitleId, aAttrs, aMediaArray);
+                break;
+                }
+            case EMPXPodcast:
+            case EMPXSong:
+                {
+                FindEpisodesL(aCriteria, attributes.Array(), aMediaArray);
+                break;
+                }
+            case EMPXGenre:
+            case EMPXPlaylist:
+            case EMPXArtist:
+            case EMPXComposer:
+            default:
+                {
+                DbCategoryL(category)->FindAllL(aCriteria, attributes.Array(), aMediaArray);
+                break;
+                }
+            }
+        }
+    else
+        {
+        TMPXPodcastCategory category =
+             aCriteria.ValueTObjectL<TMPXPodcastCategory>(KMPXMediaPodcastCategoryGroup);
+
+        switch (category)
+            {
+            case EMPXTitle:
+                {
+                if (!aCriteria.IsSupported(KMPXMediaGeneralId))
+                    {
+                    User::Leave(KErrArgument);
+                    }
+                // return all episodes within this title
+                TMPXItemId episodeTitleId = aCriteria.ValueTObjectL<TMPXItemId>(KMPXMediaGeneralId);
+                GetEpisodesMatchingTitleL(episodeTitleId, aAttrs, aMediaArray);
+                break;
+                }
+            case EMPXPubDate:
+                {
+                if (!aCriteria.IsSupported(KMPXMediaGeneralId))
+                    {
+                    User::Leave(KErrArgument);
+                    }
+
+                TMPXItemId categoryId = aCriteria.ValueTObjectL<TMPXItemId>(KMPXMediaGeneralId);
+
+                // zero out the high 4 bits which indicate the general category
+                categoryId.iId2 &= 0x00FFFFFF;
+                GetEpisodesMatchingPublishPlaylistL(categoryId.iId2 + KPublishTodayPlaylistUID, // offset by KPublishTodayPlaylistUID
+                    aAttrs, EFalse, aMediaArray);
+                break;
+                }
+            case EMPXRecentlyAdded:
+            case EMPXNotYetPlayed:
+                {
+                break;
+                }
+            case EMPXAll:
+            case EMPXEpisode:
+            case EMPXNew:
+            case EMPXPartlyPlayed:
+            case EMPXCompletelyPlayed:
+                {
+                FindEpisodesL(aCriteria, attributes.Array(), aMediaArray);
+                break;
+                }
+            default:
+                User::Leave(KErrNotSupported);
+            }
+        }
+
+    CleanupStack::PopAndDestroy(&attributes);
+    }
+
+// ----------------------------------------------------------------------------
+// Get episode(s) from the music table that match the given criteria
+// ----------------------------------------------------------------------------
+//
+void CMPXPodcastDbHandler::FindEpisodesL(
+    const CMPXMedia& aCriteria,
+    const TArray<TMPXAttribute>& aAttrs,
+    CMPXMediaArray& aMediaArray)
+    {
+    MPX_FUNC("CMPXPodcastDbHandler::FindEpisodesL");
+
+    TMPXGeneralType type(EMPXNoType);
+    if (!aCriteria.IsSupported(KMPXMediaGeneralType))
+        {
+        User::Leave(KErrArgument);
+        }
+    type = aCriteria.ValueTObjectL<TMPXGeneralType>(KMPXMediaGeneralType);
+
+    TMPXPodcastType podcastType(EMPXPodcastNoType);
+    if (aCriteria.IsSupported(KMPXMediaPodcastType))
+        {
+        podcastType = aCriteria.ValueTObjectL<TMPXPodcastType>(KMPXMediaPodcastType);
+        }
+
+    TUint32 id(0);
+    if (aCriteria.IsSupported(KMPXMediaGeneralId))
+        {
+        id = aCriteria.ValueTObjectL<TMPXItemId>(KMPXMediaGeneralId);
+        }
+
+    TUint32 containerId(0);
+    if (aCriteria.IsSupported(KMPXMediaGeneralContainerId))
+        {
+        containerId = aCriteria.ValueTObjectL<TMPXItemId>(KMPXMediaGeneralContainerId);
+        }
+
+    MPX_TRAPD(err, iDbPodcast->FindEpisodesL(id, containerId, type, podcastType,
+        aCriteria, aAttrs, aMediaArray));
+    if (err == KErrNotSupported)
+        {
+        User::Leave(KErrNotFound);
+        }
+
+    User::LeaveIfError(err);
+    }
+
+// ----------------------------------------------------------------------------
+// Add episode to collection
+// ----------------------------------------------------------------------------
+//
+TUint32 CMPXPodcastDbHandler::DoAddEpisodeL(
+    const CMPXMedia& aMedia)
+    {
+    MPX_FUNC("CMPXPodcastDbHandler::DoAddEpisodeL");
+
+    if (!aMedia.IsSupported(KMPXMediaGeneralUri))
+        {
+        User::Leave(KErrArgument);
+        }
+
+    TDriveUnit drive(aMedia.ValueText(KMPXMediaGeneralUri));
+    return iDbPodcast->AddEpisodeL(aMedia, drive);
+    }
+
+// ----------------------------------------------------------------------------
+// Update a episode in the collection
+// ----------------------------------------------------------------------------
+//
+CMPXDbActiveTask::TChangeVisibility CMPXPodcastDbHandler::DoUpdateEpisodeL(
+    const CMPXMedia& aMedia,
+    CMPXMessageArray& aItemChangedMessages)
+    {
+    MPX_FUNC("CMPXPodcastDbHandler::DoUpdateEpisodeL");
+
+    CMPXDbActiveTask::TChangeVisibility visibleChange(CMPXDbActiveTask::ENotVisibile);
+    TUint32 curId(0);
+    TUint32 newId(0);
+    TInt curDrive(KErrNotFound);
+    TInt newDrive(KErrNotFound);
+
+    // find the episode by Id and update it
+    if( aMedia.IsSupported(KMPXMediaGeneralId))
+        {
+        curId = (aMedia.ValueTObjectL<TMPXItemId>(KMPXMediaGeneralId)).iId2;
+        curDrive = iDbPodcast->GetDriveL(curId);
+        }
+    // find the episode by URI and update it
+    if(aMedia.IsSupported(KMPXMediaGeneralUri))
+        {
+        const TDesC& uri = aMedia.ValueText(KMPXMediaGeneralUri);
+        if (uri.Length() == 0)
+            {
+            User::Leave( KErrArgument );
+            }
+
+        newDrive = TDriveUnit(uri);
+        newId = MPXDbCommonUtil::GenerateUniqueIdL(iFs, EMPXCollection, uri, EFalse);
+        }
+    if (!curId && !newId)
+        {
+        User::Leave(KErrNotSupported);
+        }
+
+    TInt driveId = (curDrive != KErrNotFound) ? curDrive : newDrive;
+
+    if (driveId != KErrNotFound)
+        {
+        TUint32 episodeId = curId ? curId : newId;
+
+        // Update the Podcast table
+        visibleChange = iDbPodcast->UpdateEpisodeL(episodeId, aMedia, aItemChangedMessages);
+        }
+
+    return visibleChange;
+    }
+
+// ----------------------------------------------------------------------------
+// CMPXPodcastDbHandler::DoRemoveEpisodeL
+// ----------------------------------------------------------------------------
+//
+void CMPXPodcastDbHandler::DoRemoveEpisodeL(
+    TUint32 aEpisodeId,
+    CDesCArray& aUriArray,
+    CMPXMessageArray& aItemChangedMessages,
+    TBool aDeleteRecord)
+    {
+    MPX_FUNC("CMPXPodcastDbHandler::DoRemoveEpisodeL");
+
+    TBool deleteRecord(ETrue);
+
+#if defined (__MTP_PROTOCOL_SUPPORT)
+    // Mark the song record as deleted if the following is true; otherwise, delete the
+    // song record.
+    //
+    // A client other than MTP has initiated this song deletion (aDeleteRecord is EFalse)
+    // and MTP has turned on its cenrep key to save deleted records and current number of
+    // saved deleted records has not exceeded its maximum, KMCMaxSavedDeletedRecords.
+    //
+    // Songs are marked as deleted in order to support auto-sync. MTP will delete these
+    // marked records at the end of each session via CleanupDeletedMediasL.
+    //
+    // For performance consideration, if the number of saved records exceeds its maximum,
+    // song record will be deleted.
+    if (!aDeleteRecord && SaveDeletedSongs())
+        {
+        TUint32 savedDeletedRecordCount(iDbAuxiliary->SaveDeletedRecordCountL());
+        MPX_DEBUG2("Current number of saved deleted record count is %d", savedDeletedRecordCount);
+
+        if (savedDeletedRecordCount < KMCMaxSavedDeletedRecords)
+            {
+            deleteRecord = EFalse;
+            TInt drive = iDbPodcast->GetDriveL(aEpisodeId);
+            TUint32 savedDeletedDriveRecordCount(iDbAuxiliary->SaveDeletedRecordCountL(drive));
+            iDbAuxiliary->SetSaveDeletedRecordCountL(drive,++savedDeletedDriveRecordCount);
+            }
+        }
+#endif
+
+    // delete the episode 
+	// IsAdd is passed EFalse to ensure the episode count will be decremented
+    iDbPodcast->DeleteEpisodeL(aEpisodeId, aUriArray, aItemChangedMessages, EFalse, deleteRecord);
+    }
+
+// ----------------------------------------------------------------------------
+// CMPXPodcastDbHandler::DoRemoveEpisodesMatchingCategoryL
+// ----------------------------------------------------------------------------
+//
+void CMPXPodcastDbHandler::DoRemoveEpisodesMatchingCategoryL(
+    TMPXGeneralCategory aCategory,
+    TUint32 aCategoryId,
+    CDesCArray& aUriArray,
+    CMPXMessageArray& aItemChangedMessages)
+    {
+    MPX_FUNC("CMPXPodcastDbHandler::DoRemoveEpisodesMatchingCategoryL");
+    iDbPodcast->DeleteCategoryL(aCategory, aCategoryId, aUriArray,
+        aItemChangedMessages);
+    }
+
+// ----------------------------------------------------------------------------
+// CMPXPodcastDbHandler::DoRemoveEpisodesMatchingPublishDateCategoryL
+// ----------------------------------------------------------------------------
+//
+void CMPXPodcastDbHandler::DoRemoveEpisodesMatchingPublishDateCategoryL(
+    TUint32 aCategoryId,
+    CDesCArray& aUriArray,
+    CMPXMessageArray& aItemChangedMessages)
+    {
+    MPX_FUNC("CMPXPodcastDbHandler::DoRemoveEpisodesMatchingPublishDateCategoryL");
+
+    switch (aCategoryId + KPublishTodayPlaylistUID)
+        {
+        case KPublishTodayPlaylistUID:
+            MPX_DEBUG1 (_L("CMPXPodcastDbHandler::DoRemoveEpisodesMatchingPublishDateCategoryL: Published Today"));
+            iDbPodcast->DeleteTodayEpisodesL(aUriArray, aItemChangedMessages);
+            break;
+
+        case KPublishYesterdayPlaylistUID:
+            MPX_DEBUG1 (_L("CMPXPodcastDbHandler::DoRemoveEpisodesMatchingPublishDateCategoryL: Published Yesterday"));
+            iDbPodcast->DeleteYesterdayEpisodesL(aUriArray, aItemChangedMessages);
+            break;
+
+        case KPublishThisWeekPlaylistUID:
+            MPX_DEBUG1 (_L("CMPXPodcastDbHandler::DoRemoveEpisodesMatchingPublishDateCategoryL: Published This Week"));
+            iDbPodcast->DeleteThisWeekEpisodesL(aUriArray, aItemChangedMessages);
+            break;
+
+        case KPublishLastWeekPlaylistUID:
+            MPX_DEBUG1 (_L("CMPXPodcastDbHandler::DoRemoveEpisodesMatchingPublishDateCategoryL: Published Last Week"));
+            iDbPodcast->DeleteLastWeekEpisodesL(aUriArray, aItemChangedMessages);
+            break;
+
+        case KPublish2WeeksAgoPlaylistUID:
+            MPX_DEBUG1 (_L("CMPXPodcastDbHandler::DoRemoveEpisodesMatchingPublishDateCategoryL: Published 2 Weeks Ago"));
+            iDbPodcast->Delete2WeeksAgoEpisodesL(aUriArray, aItemChangedMessages);
+            break;
+
+        case KPublish3WeeksAgoPlaylistUID:
+            MPX_DEBUG1 (_L("CMPXPodcastDbHandler::DoRemoveEpisodesMatchingPublishDateCategoryL: Published 3 Weeks Ago"));
+            iDbPodcast->Delete3WeeksAgoEpisodesL(aUriArray, aItemChangedMessages);
+            break;
+
+        case KPublishLastMonthPlaylistUID:
+            MPX_DEBUG1 (_L("CMPXPodcastDbHandler::DoRemoveEpisodesMatchingPublishDateCategoryL: Published Last Month"));
+            iDbPodcast->DeleteLastMonthEpisodesL(aUriArray, aItemChangedMessages);
+            break;
+
+        case KPublishEarlierPlaylistUID:
+            MPX_DEBUG1 (_L("CMPXPodcastDbHandler::DoRemoveEpisodesMatchingPublishDateCategoryL: Published Earlier"));
+            iDbPodcast->DeleteEarlierEpisodesL(aUriArray, aItemChangedMessages);
+            break;
+
+        case KPublishUnknownPlaylistUID:
+            MPX_DEBUG1 (_L("CMPXPodcastDbHandler::DoRemoveEpisodesMatchingPublishDateCategoryL: Published Unknown"));
+            iDbPodcast->DeleteUnknownEpisodesL(aUriArray, aItemChangedMessages);
+            break;
+
+        default:
+            MPX_DEBUG2 (_L("CMPXPodcastDbHandler::DoRemoveEpisodesMatchingPublishDateCategoryL: Invalid publish date ID [%d]"), aCategoryId);
+            // TODO: Leave with error?
+            break;
+        }
+    }
+
+// ----------------------------------------------------------------------------
+// CMPXPodcastDbHandler::ProcessPodcastFoldersL
+// ----------------------------------------------------------------------------
+//
+void CMPXPodcastDbHandler::ProcessPodcastFoldersL(
+    const CDesCArray& aFolders)
+    {
+    MPX_FUNC("CMPXPodcastDbHandler::ProcessPodcastFoldersL");
+
+    TInt count(aFolders.MdcaCount());
+    for (TInt i = 0; i < count; ++i)
+        {
+        TPtrC16 folder = aFolders.MdcaPoint(i);
+
+        // check if disk is inserted and act accordingly
+        TDriveUnit driveUnit(folder);
+        if (!iFs.IsValidDrive(driveUnit))
+            {
+            User::Leave(KErrArgument);
+            }
+
+        // append the drive to the drive list
+        iDbDrives.AppendL(driveUnit);
+        }
+    }
+
+// ----------------------------------------------------------------------------
+// CMPXPodcastDbHandler::DbCategoryL
+// ----------------------------------------------------------------------------
+//
+CMPXDbCategory* CMPXPodcastDbHandler::DbCategoryL(
+    TMPXGeneralCategory aCategory) const
+    {
+    MPX_FUNC("CMPXPodcastDbHandler::DbCategoryL");
+
+    CMPXDbCategory* dbCategory(NULL);
+    switch (aCategory)
+        {
+        case EMPXArtist:
+            {
+            dbCategory = iDbArtist;
+            break;
+            }
+        case EMPXAlbum:
+            {
+            dbCategory = iDbAlbum;
+            break;
+            }
+        case EMPXGenre:
+            {
+            dbCategory = iDbGenre;
+            break;
+            }
+        case EMPXComposer:
+            {
+            dbCategory = iDbComposer;
+            break;
+            }
+        default:
+            User::Leave(KErrNotSupported);
+        }
+
+    return dbCategory;
+    }
+
+// ----------------------------------------------------------------------------
+// Starts a transaction on all databases
+// ----------------------------------------------------------------------------
+//
+void CMPXPodcastDbHandler::BeginTransactionL()
+    {
+    MPX_FUNC("CMPXPodcastDbHandler::BeginTransactionL");
+    iDbManager->BeginL();
+    }
+
+// ----------------------------------------------------------------------------
+// Ends a transaction on all databases
+// ----------------------------------------------------------------------------
+//
+void CMPXPodcastDbHandler::EndTransactionL(
+    TInt aError)
+    {
+    MPX_FUNC("CMPXPodcastDbHandler::EndTransactionL");
+
+    if (aError)
+        {
+        iDbManager->RollbackL();
+        
+        // KSqlDbCorrupted indicates DB corrupted, need to recreate.
+        if ( aError != KSqlDbCorrupted )
+            {
+            User::Leave(aError);
+            }
+        }
+    else
+        {
+        iDbManager->CommitL();
+        }
+    }
+
+// ----------------------------------------------------------------------------
+// Checks if the database is currently in a transaction
+// ----------------------------------------------------------------------------
+//
+TBool CMPXPodcastDbHandler::InTransaction()
+    {
+    MPX_FUNC("CMPXPodcastDbHandler::InTransaction");
+    return iDbManager->InTransaction();
+    }
+
+// ----------------------------------------------------------------------------
+// Verifies that the volume ID of the database matches the drive
+// ----------------------------------------------------------------------------
+//
+void CMPXPodcastDbHandler::VerifyVolumeIdL( TInt aDrive )
+    {
+    MPX_DEBUG1("CMPXPodcastDbHandler::VerifyVolumeIdL <--");
+
+    if( iDbManager->IsOpen(aDrive) )
+        {
+        TVolumeInfo volInfo;
+        iFs.Volume(volInfo, aDrive );
+        TUint curId(volInfo.iUniqueID);
+
+        TInt volId = iDbAuxiliary->IdL( aDrive );
+
+        // New database, no volume id set, mask out top bit because this is an uint
+        //
+        MPX_DEBUG3("CMPXPodcastDbHandler::VerifyVolumeIdL drive:%i db:%i", curId, volId);
+        if( volId == 0 && (curId&0x7FFFFFFF) )
+            {
+            MPX_DEBUG1("CMPXPodcastDbHandler::VerifyVolumeIdL -- New ID");
+            BeginTransactionL();
+            TRAPD( err, iDbAuxiliary->SetIdL( aDrive, curId&0x7FFFFFFF ) );
+            EndTransactionL( err );
+
+            // KSqlDbCorrupted indicates DB corrupted, need to recreate.
+            if ( err == KSqlDbCorrupted )
+                {
+                MPX_DEBUG1("CMPXPodcastDbHandler::VerifyVolumeIdL -- Corrupted DB");
+                iDbManager->RecreateDatabaseL( aDrive );
+                BeginTransactionL();
+                TRAPD( err, iDbAuxiliary->SetDBCorruptedL( ETrue ) );
+                EndTransactionL( err );
+                }
+            }
+        // Unmatched volume id, mark db as corrupt
+        //
+        else if ( (curId&0x7FFFFFFF) != (volId&0x7FFFFFFFF) )
+            {
+            MPX_DEBUG1("CMPXPodcastDbHandler::VerifyVolumeIdL -- ID match FAILED");
+            iDbManager->RecreateDatabaseL( aDrive );
+            BeginTransactionL();
+            TRAPD( err, iDbAuxiliary->SetDBCorruptedL( ETrue ) );
+            EndTransactionL( err );
+            }
+        }
+    MPX_DEBUG1("CMPXPodcastDbHandler::VerifyVolumeIdL -->");
+    }
+
+
+// ----------------------------------------------------------------------------
+// Verifies that the volume ID of the database matches the drive
+// ----------------------------------------------------------------------------
+//
+void CMPXPodcastDbHandler::VerifyVolumeIdL()
+    {
+    MPX_DEBUG1("CMPXPodcastDbHandler::VerifyVolumeIdL <--");
+    TInt count( iDbDrives.Count() );
+    for( TInt i=0; i<count; ++i )
+        {
+        VerifyVolumeIdL(iDbDrives[i]);
+        }
+    MPX_DEBUG1("CMPXPodcastDbHandler::VerifyVolumeIdL -->");
+    }
+
+// ----------------------------------------------------------------------------
+// Checks if there is a drive that has a low disk space
+// ----------------------------------------------------------------------------
+//
+void CMPXPodcastDbHandler::CheckDiskSpaceOnDrivesL()
+    {
+    MPX_DEBUG1("CMPXPodcastDbHandler::CheckDiskSpaceOnDrivesL <--");
+
+    TInt count( iDbDrives.Count() );
+    for( TInt index=0; index<count; ++index )
+        {
+        iDbManager->CheckDiskSpaceL(iDbDrives[index]);
+        }
+    MPX_DEBUG1("CMPXPodcastDbHandler::CheckDiskSpaceOnDrivesL -->");
+    }
+#if defined (__MTP_PROTOCOL_SUPPORT)
+
+// ----------------------------------------------------------------------------
+// CMPXPodcastDbHandler::SaveDeletedSongs
+// ----------------------------------------------------------------------------
+//
+TBool CMPXPodcastDbHandler::SaveDeletedSongs()
+    {
+    MPX_FUNC("CMPXPodcastDbHandler::SaveDeletedSongs");
+
+    TBool saveDeletedSongs(ETrue);
+    CRepository* cenrep(NULL);
+    MPX_TRAPD(error, cenrep = CRepository::NewL(KMPXMtpSettings));
+    if (!error)
+        {
+        cenrep->Get(KMPXMtpSaveDeletedRecordFlag, saveDeletedSongs);
+        delete cenrep;
+        MPX_DEBUG2("MTP indicated to save deleted songs? %d", saveDeletedSongs);
+        }
+
+    return saveDeletedSongs;
+    }
+
+#endif
+
+// ----------------------------------------------------------------------------
+// CMPXPodcastDbHandler::AddCategoryItemL
+// ----------------------------------------------------------------------------
+//
+TUint32 CMPXPodcastDbHandler::AddCategoryItemL(
+    TMPXGeneralCategory aCategory,
+    const TDesC& aName,
+    TInt aDriveId,
+    CMPXMessageArray* aItemChangedMessages)
+    {
+    MPX_FUNC("CMPXPodcastDbHandler::AddCategoryItemL");
+
+    TBool newRecord(EFalse);
+    TUint32 id(DbCategoryL(aCategory)->AddItemL(aName, aDriveId, newRecord,
+        (aCategory != EMPXGenre)));
+    if (newRecord && aItemChangedMessages)
+        {
+        MPXDbCommonUtil::AddItemChangedMessageL(*aItemChangedMessages, id,
+            EMPXItemInserted, aCategory, KDBPluginUid);
+        }
+
+    return id;
+    }
+
+// ----------------------------------------------------------------------------
+// CMPXPodcastDbHandler::DeleteEpisodeForCategoryL
+// ----------------------------------------------------------------------------
+//
+void CMPXPodcastDbHandler::DeleteEpisodeForCategoryL(
+    TMPXGeneralCategory aCategory,
+    TUint32 aCategoryId,
+    TInt aDriveId,
+    CMPXMessageArray* aItemChangedMessages)
+    {
+    MPX_FUNC("CMPXPodcastDbHandler::DeleteEpisodeForCategoryL");
+    DbCategoryL(aCategory)->DecrementEpisodesForCategoryL(aCategoryId, aDriveId,
+        aItemChangedMessages);
+    }
+
+#ifdef RD_MULTIPLE_DRIVE
+
+// ----------------------------------------------------------------------------------------------------------
+// Retrieve all visible podcast folder locations
+// ----------------------------------------------------------------------------------------------------------
+//
+CDesCArrayFlat* CMPXPodcastDbHandler::GetPodcastFoldersL()
+    {
+    MPX_FUNC("CMPXPodcastDbHandler::GetPodcastFoldersL()");
+    TDriveList driveList;
+    TInt driveCount(0);
+    User::LeaveIfError(DriveInfo::GetUserVisibleDrives(iFs, driveList, driveCount));
+    MPX_DEBUG2 ("CMPXDbHandler::GetPodcastFoldersL() - driveCount = %d", driveCount);
+
+    CDesCArrayFlat* folders = new (ELeave) CDesCArrayFlat(1); // granularity
+    CleanupStack::PushL(folders);
+
+    for (TInt i = EDriveA; i <= EDriveZ; i++)
+        {
+        if ((driveList[i]) && (!IsRemoteDrive(static_cast<TDriveNumber>(i))))
+            {
+            if (i == EDriveC)
+                {
+                // Append the default phone memory path to the list
+                // of music folders
+                TPtrC rootPath(PathInfo::PhoneMemoryRootPath());
+                folders->AppendL(rootPath);
+                MPX_DEBUG2("CMPXDbHandler::GetPodcastFoldersL() - adding...%S", &rootPath);
+                }
+            else
+                {
+                // Get drive letter
+                TChar driveChar;
+                User::LeaveIfError(iFs.DriveToChar(i, driveChar));
+
+                // Append visible drive to list of music folders
+                TBuf<2> drive;
+                drive.Append(driveChar);
+                drive.Append(_L(":"));
+                folders->AppendL(drive);
+                MPX_DEBUG2 ("CMPXDbHandler::GetPodcastFoldersL() - adding...%S", &drive);
+                }
+            }
+        }
+
+    CleanupStack::Pop(folders);
+    return folders;
+    }
+
+#endif // RD_MULTIPLE_DRIVE
+
+// ---------------------------------------------------------------------------
+// CMPXPodcastDbHandler::IsRemoteDrive
+// ---------------------------------------------------------------------------
+//
+TBool CMPXPodcastDbHandler::IsRemoteDrive(TDriveNumber aDrive)
+    {
+    return iDbManager->IsRemoteDrive(aDrive);
+    }
+
+// End of File
+
+