/*
* Copyright (c) 2007 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: Responsible for interaction with the playlist tables.
*
*/
// INCLUDE FILES
#include <f32file.h>
#include <mpxlog.h>
#include <mpxmediacontainerdefs.h>
#include "mpxdbcommonutil.h"
#include "mpxdbcommondef.h"
#include "mpxdbcommonstd.h"
#include "mpxcollectiondbdef.h"
#include "mpxdbmanager.h"
#include "mpxdbutil.h"
#include "mpxdbpluginqueries.h"
#include "mpxdbplaylistsongs.h"
#include "mpxdbplaylist.h"
// CONSTANTS
// UniqueID column in Uris requests
const TInt KColUniqueID = 0;
// URI column in Uris requests
const TInt KColUri = 1;
// ============================ MEMBER FUNCTIONS ==============================
// ----------------------------------------------------------------------------
// Two-phased constructor.
// ----------------------------------------------------------------------------
//
CMPXDbPlaylist* CMPXDbPlaylist::NewL(
CMPXDbManager& aDbManager,
MMPXDbPlaylistObserver& aObserver)
{
MPX_FUNC("CMPXDbPlaylist::NewL");
CMPXDbPlaylist* self = CMPXDbPlaylist::NewLC(aDbManager, aObserver);
CleanupStack::Pop(self);
return self;
}
// ----------------------------------------------------------------------------
// Two-phased constructor.
// ----------------------------------------------------------------------------
//
CMPXDbPlaylist* CMPXDbPlaylist::NewLC(
CMPXDbManager& aDbManager,
MMPXDbPlaylistObserver& aObserver)
{
MPX_FUNC("CMPXDbPlaylist::NewLC");
CMPXDbPlaylist* self = new (ELeave) CMPXDbPlaylist(aDbManager, aObserver);
CleanupStack::PushL(self);
self->ConstructL();
return self;
}
// ----------------------------------------------------------------------------
// Destructor
// ----------------------------------------------------------------------------
//
CMPXDbPlaylist::~CMPXDbPlaylist()
{
MPX_FUNC("CMPXDbPlaylist::~CMPXDbPlaylist");
delete iPlaylistSongs;
}
// ----------------------------------------------------------------------------
// Constructor
// ----------------------------------------------------------------------------
//
CMPXDbPlaylist::CMPXDbPlaylist(
CMPXDbManager& aDbManager,
MMPXDbPlaylistObserver& aObserver) :
CMPXDbTable(aDbManager),
iObserver(aObserver)
{
MPX_FUNC("CMPXDbPlaylist::CMPXDbPlaylist");
}
// ----------------------------------------------------------------------------
// Second phase constructor.
// ----------------------------------------------------------------------------
//
void CMPXDbPlaylist::ConstructL()
{
MPX_FUNC("CMPXDbPlaylist::ConstructL");
BaseConstructL();
iPlaylistSongs = CMPXDbPlaylistSongs::NewL(iDbManager);
}
// ----------------------------------------------------------------------------
// CMPXDbPlaylist::AddPlaylistL
// ----------------------------------------------------------------------------
//
TUint32 CMPXDbPlaylist::AddPlaylistL(
const CMPXMedia& aMedia)
{
MPX_FUNC("CMPXDbPlaylist::AddPlaylistL");
// make sure the playlist and the corresponding songs are deleted
TUint32 playlistId(MPXDbCommonUtil::GenerateUniqueIdL(iDbManager.Fs(), EMPXPlaylist,
aMedia.ValueText(KMPXMediaGeneralUri), EFalse));
DeletePlaylistNoUriL(playlistId);
// add the playlist
return DoAddPlaylistL(aMedia, TDriveUnit(aMedia.ValueText(KMPXMediaGeneralUri)));
}
// ----------------------------------------------------------------------------
// CMPXDbPlaylist::AddSongsL
// ----------------------------------------------------------------------------
//
void CMPXDbPlaylist::AddSongsL(
TUint32 aPlaylistId,
const CMPXMediaArray& aMediaArray)
{
MPX_FUNC("CMPXDbPlaylist::AddSongsL");
// get the drive ID of corresponding playlist
TInt drive(GetDriveIdL(aPlaylistId));
// add the songs
iPlaylistSongs->AddSongsL(aPlaylistId, aMediaArray, drive);
// update the time for the playlist
UpdatePlaylistTimeL(aPlaylistId, drive);
}
// ----------------------------------------------------------------------------
// CMPXDbPlaylist::UpdatePlaylistL
// ----------------------------------------------------------------------------
//
void CMPXDbPlaylist::UpdatePlaylistL(
const CMPXMedia& aMedia,
CMPXMessage& aMessage,
TInt aDriveId)
{
MPX_FUNC("CMPXDbPlaylist::UpdatePlaylistL");
TUint32 playlistId((aMedia.ValueTObjectL<TMPXItemId>(KMPXMediaGeneralId)).iId2);
DoUpdatePlaylistL(playlistId, aMedia, aDriveId, aMessage);
}
// ----------------------------------------------------------------------------
// CMPXDbPlaylist::UpdateSongL
// ----------------------------------------------------------------------------
//
TBool CMPXDbPlaylist::UpdateSongL(
const CMPXMedia& aMedia,
TBool aResetFlags,
CMPXMessageArray* aItemChangedMessages /* = NULL */)
{
MPX_FUNC("CMPXDbPlaylist::UpdateSongL");
// find the song ID
TInt oldSongId(0);
TInt newSongId(0);
if (aMedia.IsSupported(KMPXMediaGeneralId))
{
oldSongId = (aMedia.ValueTObjectL<TMPXItemId>(KMPXMediaGeneralId)).iId2;
}
if (aMedia.IsSupported(KMPXMediaGeneralUri))
{
newSongId = MPXDbCommonUtil::GenerateUniqueIdL(iDbManager.Fs(), EMPXCollection,
aMedia.ValueText(KMPXMediaGeneralUri), EFalse);
}
if ( !aMedia.IsSupported( KMPXMediaGeneralId ) && !aMedia.IsSupported( KMPXMediaGeneralUri ))
{
User::Leave( KErrArgument );
}
if ( newSongId <= 0 )
{
newSongId = oldSongId;
}
if ( oldSongId <= 0 )
{
oldSongId = newSongId;
}
// update the PlaylistSongs and PlaylistSongInfo tables first
TBool updated(EFalse);
TBool visible(iPlaylistSongs->UpdateSongL( oldSongId, aMedia, aResetFlags, updated ));
TBool bSongInPlaylists( EFalse );
if (updated)
{
UpdatePlaylistsForSongL( newSongId, aItemChangedMessages,bSongInPlaylists );
}
return visible;
}
// ----------------------------------------------------------------------------
// CMPXDbPlaylist::DeleteSongL
// ----------------------------------------------------------------------------
//
void CMPXDbPlaylist::DeleteSongL(
TUint32 aSongId,
CMPXMessageArray& aItemChangedMessages)
{
MPX_FUNC("CMPXDbPlaylist::DeleteSongL");
TBool bSongInPlaylists(EFalse);
// add item changed messages for all playlists that contain the song
UpdatePlaylistsForSongL (aSongId, &aItemChangedMessages, bSongInPlaylists);
if (bSongInPlaylists)
{
// delete the song from the PlaylistSongs and PlaylistSongInfo tables
iPlaylistSongs->DeleteSongL (aSongId);
}
}
// ----------------------------------------------------------------------------
// CMPXDbPlaylist::DeleteSongL
// ----------------------------------------------------------------------------
//
void CMPXDbPlaylist::DeleteSongL(
TUint32 aPlaylistId,
TUint32 aSongId,
TInt aOrdinal)
{
MPX_FUNC("CMPXDbPlaylist::DeleteSongL");
// get playlist drive
TInt drive(GetDriveIdL(aPlaylistId));
// delete the song from the PlaylistSongs / PlaylistSongInfo tables
iPlaylistSongs->DeleteSongL(aPlaylistId, aSongId, aOrdinal, drive);
// update the time for the playlist
UpdatePlaylistTimeL(aPlaylistId, drive);
}
// ----------------------------------------------------------------------------
// CMPXDbPlaylist::DeletePlaylistL
// ----------------------------------------------------------------------------
//
HBufC* CMPXDbPlaylist::DeletePlaylistL(
TUint32 aPlaylistId)
{
MPX_FUNC("CMPXDbPlaylist::DeletePlaylistL");
// get the uri
HBufC* uri = GetUriL(aPlaylistId);
if (uri)
{
CleanupStack::PushL(uri);
TDriveUnit drive(*uri);
// delete the songs from the PlaylistSongs table
iPlaylistSongs->DeleteSongsL(aPlaylistId, drive);
// delete the playlist record from the Playlist table
iDbManager.ExecuteQueryL(drive, KQueryPlaylistDelete, aPlaylistId);
CleanupStack::Pop(uri);
}
return uri;
}
// ----------------------------------------------------------------------------
// CMPXDbPlaylist::DeletePlaylistNoUriL
// ----------------------------------------------------------------------------
//
void CMPXDbPlaylist::DeletePlaylistNoUriL(
TUint32 aPlaylistId)
{
MPX_FUNC("CMPXDbPlaylist::DeletePlaylistNoUriL");
TInt drive(0);
MPX_TRAPD(err, drive = GetDriveIdL(aPlaylistId));
if (err != KErrNotFound)
{
User::LeaveIfError(err);
// delete the songs from the PlaylistSongs table
iPlaylistSongs->DeleteSongsL(aPlaylistId, drive);
// delete the playlist record from the Playlist table
iDbManager.ExecuteQueryL(drive, KQueryPlaylistDelete, aPlaylistId);
}
}
// ----------------------------------------------------------------------------
// CMPXDbPlaylist::DeleteAllPlaylistsL
// ----------------------------------------------------------------------------
//
void CMPXDbPlaylist::DeleteAllPlaylistsL()
{
MPX_FUNC("CMPXDbPlaylist::DeleteAllPlaylistsL");
// delete the songs from the PlaylistSongs table
iPlaylistSongs->DeleteAllSongsL();
// delete all playlists
iDbManager.ExecuteQueryL(KDbManagerAllDrives, KQueryPlaylistDeleteAll);
}
// ----------------------------------------------------------------------------
// CMPXDbPlaylist::CountL
// ----------------------------------------------------------------------------
//
TInt CMPXDbPlaylist::CountL()
{
MPX_FUNC("CMPXDbPlaylist::CountL");
return ExecuteSumQueryL(KQueryPlaylistCount);
}
// ----------------------------------------------------------------------------
// CMPXDbPlaylist::GetPlaylistL
// ----------------------------------------------------------------------------
//
void CMPXDbPlaylist::GetPlaylistL(
TUint32 aPlaylistId,
const TArray<TMPXAttribute>& aAttrs,
CMPXMedia& aMedia)
{
MPX_FUNC("CMPXDbPlaylist::GetPlaylistL");
ExecuteMediaQueryL(aAttrs, aMedia, KQueryPlaylistGet, aPlaylistId);
}
// ----------------------------------------------------------------------------
// CMPXDbPlaylist::GetAllPlaylistsL
// ----------------------------------------------------------------------------
//
void CMPXDbPlaylist::GetAllPlaylistsL(
const TArray<TMPXAttribute>& aAttrs,
CMPXMediaArray& aMediaArray)
{
MPX_FUNC("CMPXDbPlaylist::GetAllPlaylistsL");
ExecuteMediaQueryL(aAttrs, aMediaArray, KQueryPlaylistGetAll);
}
// ----------------------------------------------------------------------------
// CMPXDbPlaylist::GetNameL
// ----------------------------------------------------------------------------
//
HBufC* CMPXDbPlaylist::GetNameL(
TUint32 aPlaylistId)
{
MPX_FUNC("CMPXDbPlaylist::GetNameL");
RSqlStatement recordset(GetPlaylistRecordL(aPlaylistId));
CleanupClosePushL(recordset);
HBufC* name(NULL);
TInt err(KErrNone);
if ((err = recordset.Next()) == KSqlAtRow)
{
name = MPXDbCommonUtil::GetColumnTextL(recordset, EPlaylistName).AllocL();
}
CleanupStack::PopAndDestroy(&recordset);
if (err != KSqlAtEnd)
{
User::LeaveIfError(err);
}
if (name == NULL)
{
User::LeaveIfError(KErrNotFound);
}
return name;
}
// ----------------------------------------------------------------------------
// CMPXDbPlaylist::GetUriL
// ----------------------------------------------------------------------------
//
HBufC* CMPXDbPlaylist::GetUriL(
TUint32 aPlaylistId)
{
MPX_FUNC("CMPXDbPlaylist::GetUriL");
RSqlStatement recordset(GetPlaylistRecordL(aPlaylistId));
CleanupClosePushL(recordset);
HBufC* uri(NULL);
TInt err(KErrNone);
if ((err = recordset.Next()) == KSqlAtRow)
{
uri = MPXDbCommonUtil::CreateFullPathL(
MPXDbCommonUtil::GetDriveIdMatchVolIdL(iDbManager.Fs(),
recordset.ColumnInt64(EPlaylistVolumeId)),
MPXDbCommonUtil::GetColumnTextL(recordset, EPlaylistUri));
}
CleanupStack::PopAndDestroy(&recordset);
if (err != KSqlAtEnd)
{
User::LeaveIfError(err);
}
if (uri == NULL)
{
User::LeaveIfError(KErrNotFound);
}
return uri;
}
// ----------------------------------------------------------------------------
// CMPXDbPlaylist::GetIdL
// ----------------------------------------------------------------------------
//
TUint32 CMPXDbPlaylist::GetIdL(
const TDesC& aUri)
{
MPX_FUNC("CMPXDbPlaylist::GetIdL");
HBufC* uri = MPXDbCommonUtil::ProcessPatternCharsLC( aUri );
TUint32 ret = ExecuteIntQueryL(
KQueryLikePlaylistId, uri->Mid( KMCPathStartPos ) );
CleanupStack::PopAndDestroy( uri );
return ret;
}
// ----------------------------------------------------------------------------
// CMPXDbPlaylist::FindAllL
// ----------------------------------------------------------------------------
//
void CMPXDbPlaylist::FindAllL(
const CMPXMedia& aCriteria,
const TArray<TMPXAttribute>& aAttrs,
CMPXMediaArray& aMediaArray)
{
MPX_FUNC("CMPXDbPlaylist::FindAllL");
// process the requested attributes
// the UniqueId is always requested
TBool titleRequested(EFalse);
TBool counterRequested(EFalse);
TInt viewingColumnCount(aAttrs.Count());
for (TInt i = 0; (i < viewingColumnCount) && !(titleRequested && counterRequested); ++i)
{
if (aAttrs[i].ContentId() == KMPXMediaIdGeneral)
{
TUint attributeId(aAttrs[i].AttributeId());
if (attributeId & EMPXMediaGeneralTitle)
{
titleRequested = ETrue;
}
if (attributeId & EMPXMediaGeneralCount)
{
counterRequested = ETrue;
}
}
}
TMPXGeneralType type = aCriteria.ValueTObjectL<TMPXGeneralType>(KMPXMediaGeneralType);
const TArray<TMPXAttribute> criteria = aCriteria.Attributes();
TInt criteriaCount(criteria.Count());
// process the criteria and construct the criteria string
CDesCArrayFlat* criteriaArray = new (ELeave) CDesCArrayFlat(criteriaCount);
CleanupStack::PushL(criteriaArray);
TBool criteriaCounterSet(EFalse);
TInt criteriaCounter(0);
for (TInt i = 0; i < criteriaCount; ++i)
{
const TMPXAttribute& criterion = criteria[i];
if (type == EMPXItem && criterion == KMPXMediaGeneralId)
{
TUint32 itemId((aCriteria.ValueTObjectL<TMPXItemId>(KMPXMediaGeneralId)).iId2);
if (MPX_ITEM_CATEGORY(itemId) != EMPXPlaylist)
{
User::Leave(KErrNotSupported);
}
MPXDbCommonUtil::AddSqlCriterionL(*criteriaArray, KCriterionPlaylistUniqueId, itemId);
}
else if (criterion == KMPXMediaGeneralTitle)
{
HBufC* title = MPXDbCommonUtil::ProcessPatternCharsLC(
aCriteria.ValueText(KMPXMediaGeneralTitle));
if( type == EMPXOtherType )
{
MPXDbCommonUtil::AddSqlCriterionL(*criteriaArray, KCriterionPlaylistTitle, *title);
}
else
{
MPXDbCommonUtil::AddSqlCriterionL(*criteriaArray, KCriterionPlaylistLikeTitle, *title);
}
CleanupStack::PopAndDestroy(title);
}
else if (criterion == KMPXMediaGeneralUri)
{
MPXDbCommonUtil::AddSqlCriterionL(*criteriaArray, KCriterionPlaylistUniqueId,
MPXDbCommonUtil::GenerateUniqueIdL(iDbManager.Fs(), EMPXPlaylist,
aCriteria.ValueText(KMPXMediaGeneralUri), EFalse));
}
else if (criterion == KMPXMediaGeneralDrive)
{
const TDesC& drive(aCriteria.ValueText(KMPXMediaGeneralDrive));
TDriveUnit driveUnit(drive);
MPXDbCommonUtil::AddSqlCriterionL(*criteriaArray, KCriterionPlaylistVolumeId,
MPXDbCommonUtil::GetVolIdMatchDriveIdL(iDbManager.Fs(), driveUnit));
}
else if (criterion == KMPXMediaGeneralSynchronized)
{
MPXDbCommonUtil::AddSqlCriterionL(*criteriaArray, KCriterionPlaylistSync,
aCriteria.ValueTObjectL<TBool>(KMPXMediaGeneralSynchronized));
}
else if (criterion == KMPXMediaGeneralCount)
{
criteriaCounterSet = ETrue;
criteriaCounter = aCriteria.ValueTObjectL<TInt>(KMPXMediaGeneralCount);
}
}
// construct criteria string
HBufC* criteriaStr = MPXDbCommonUtil::StringFromArrayLC(*criteriaArray, KMCAndKeyword);
HBufC* query(NULL);
if (criteriaStr->Length() > 0)
{
// construct and execute the query
query = HBufC::NewLC(KQueryPlaylistItems().Length() + criteriaStr->Length());
query->Des().Format(KQueryPlaylistItems, criteriaStr);
}
else
{
query = HBufC::NewLC(KQueryPlaylistGetAll().Length());
query->Des().Format(KQueryPlaylistGetAll);
}
RSqlStatement recordset(iDbManager.ExecuteSelectQueryL(*query));
CleanupStack::PopAndDestroy(query);
CleanupStack::PopAndDestroy(criteriaStr);
CleanupStack::PopAndDestroy(criteriaArray);
CleanupClosePushL(recordset);
TInt err(KErrNone);
while ((err = recordset.Next()) == KSqlAtRow)
{
// Setup basic info - with first record of a group
TUint32 playlistId(recordset.ColumnInt64(EPlaylistUniqueId));
TUint32 volId(recordset.ColumnInt64(EPlaylistVolumeId));
TInt driveId = MPXDbCommonUtil::GetDriveIdMatchVolIdL(iDbManager.Fs(), volId);
TBool valid(ETrue);
TInt songCount(-1);
if (criteriaCounterSet)
{
if (driveId >= 0)
{
//valid disk
songCount = iPlaylistSongs->CountL(playlistId, driveId);
}
valid = (criteriaCounter == songCount);
}
if (valid)
{
// start a new media object
CMPXMedia* media = CMPXMedia::NewL();
CleanupStack::PushL(media);
UpdateMediaL(recordset, aAttrs, *media);
aMediaArray.AppendL(*media);
CleanupStack::PopAndDestroy(media);
}
}
CleanupStack::PopAndDestroy(&recordset);
if (err != KSqlAtEnd)
{
User::LeaveIfError(err);
}
}
// ----------------------------------------------------------------------------
// CMPXDbPlaylist::GetDriveIdL
// ----------------------------------------------------------------------------
//
TInt CMPXDbPlaylist::GetDriveIdL(
TUint32 aPlaylistId)
{
MPX_FUNC("CMPXDbPlaylist::GetDriveIdL");
return MPXDbCommonUtil::GetDriveIdMatchVolIdL(iDbManager.Fs(),
ExecuteIntQueryL(KQueryPlaylistDriveId, aPlaylistId));
}
// ----------------------------------------------------------------------------
// CMPXDbPlaylist::Songs
// ----------------------------------------------------------------------------
//
CMPXDbPlaylistSongs& CMPXDbPlaylist::Songs()
{
return *iPlaylistSongs;
}
// ----------------------------------------------------------------------------
// CMPXDbPlaylist::GetDrivePlaylistCount
// ----------------------------------------------------------------------------
//
TUint CMPXDbPlaylist::GetDrivePlaylistCountL(TInt aDrive)
{
TUint count(0);
RSqlStatement recordset(iDbManager.ExecuteSelectQueryL(aDrive,KQueryPlaylistFileCount));
CleanupClosePushL(recordset);
if (recordset.Next() != KSqlAtRow)
{
User::Leave(KErrCorrupt);
}
count = TUint(recordset.ColumnInt64(KMPXTableDefaultIndex));
CleanupStack::PopAndDestroy(&recordset);
return count;
}
// ----------------------------------------------------------------------------
// CMPXDbPlaylist::GetPlaylistUriArrayL
// ----------------------------------------------------------------------------
//
void CMPXDbPlaylist::GetPlaylistUriArrayL(TInt aDrive, TInt aFromID, TInt aRecords,
CDesCArray& aUriArr, TInt& aLastID)
{
MPX_FUNC("CMPXDbPlaylist::GetPlaylistUriArrayL");
HBufC* query = NULL;
if(aFromID == 0)
{
query = HBufC::NewLC(KQueryPlaylistGetFileUris().Length()
+ KMCIntegerLen);
query->Des().Format(KQueryPlaylistGetFileUris, aRecords);
}
else
{
query = HBufC::NewLC(KQueryPlaylistGetFileUrisFrom().Length()
+ 2*KMCIntegerLen);
query->Des().Format(KQueryPlaylistGetFileUrisFrom, aFromID, aRecords);
}
RSqlStatement playlist_rs(iDbManager.ExecuteSelectQueryL(aDrive,*query));
CleanupStack::PopAndDestroy(query);
CleanupClosePushL(playlist_rs);
TInt lastID = 0;
TInt err(KErrNone);
while((err = playlist_rs.Next()) == KSqlAtRow)
{
HBufC* fullPath = MPXDbCommonUtil::CreateFullPathL(aDrive,
MPXDbCommonUtil::GetColumnTextL(playlist_rs, KColUri));
CleanupStack::PushL(fullPath);
aUriArr.AppendL(*fullPath);
CleanupStack::PopAndDestroy(fullPath);
lastID = playlist_rs.ColumnInt(KColUniqueID);
}
CleanupStack::PopAndDestroy(&playlist_rs);
aLastID = lastID;
if (err!= KSqlAtEnd)
{
User::Leave(KErrCorrupt);
}
}
// ----------------------------------------------------------------------------
// CMPXDbPlaylist::UpdateMediaL
// ----------------------------------------------------------------------------
//
void CMPXDbPlaylist::UpdateMediaL(
RSqlStatement& aRecord,
const TArray<TMPXAttribute>& aAttrs,
CMPXMedia& aMedia)
{
MPX_FUNC("CMPXDbPlaylist::UpdateMediaL");
TBool countRequested(EFalse);
TBool durationRequested(EFalse);
TUint32 playlistId(aRecord.ColumnInt64(EPlaylistUniqueId));
TInt count(aAttrs.Count());
TUint32 volId(aRecord.ColumnInt64(EPlaylistVolumeId));
TInt driveId = MPXDbCommonUtil::GetDriveIdMatchVolIdL(iDbManager.Fs(), volId);
for (TInt i = 0; i < count; ++i)
{
TInt contentId(aAttrs[i].ContentId());
TUint attributeId(aAttrs[i].AttributeId());
if (contentId == KMPXMediaIdGeneral)
{
if (attributeId & EMPXMediaGeneralId)
{
aMedia.SetTObjectValueL<TMPXItemId>(KMPXMediaGeneralId, playlistId);
MPX_DEBUG2(" Playlist ID[%u]", playlistId);
}
if (attributeId & EMPXMediaGeneralCollectionId)
{
aMedia.SetTObjectValueL<TUid>(KMPXMediaGeneralCollectionId,
TUid::Uid(KDBPluginUid));
}
if (attributeId & EMPXMediaGeneralTitle)
{
TPtrC title(MPXDbCommonUtil::GetColumnTextL(aRecord, EPlaylistName));
aMedia.SetTextValueL(KMPXMediaGeneralTitle, title);
MPX_DEBUG2(" Title[%S]", &title);
}
if ((attributeId & EMPXMediaGeneralUri) ||
(attributeId & EMPXMediaGeneralDrive) ||
(attributeId & EMPXMediaGeneralFlags))
{
// LTAN-7GH6BZ, crash if eject memory card when adding song to existing playlist
// due to special timing issue, it is possible drive number is -1 and create a
// panic when use for TDriveUnit
MPX_DEBUG3("volId = %d, driveId = %d", volId, driveId);
// handle possibly delay from framework notification
if (driveId < 0)
{
MPX_DEBUG1("invalid driveId, leave with KErrNotReady");
User::Leave(KErrNotReady);
}
TDriveUnit driveUnit(driveId);
if (attributeId & EMPXMediaGeneralUri)
{
HBufC* fullPath = MPXDbCommonUtil::CreateFullPathL(driveUnit,
MPXDbCommonUtil::GetColumnTextL(aRecord, EPlaylistUri));
CleanupStack::PushL(fullPath);
aMedia.SetTextValueL(KMPXMediaGeneralUri, *fullPath);
MPX_DEBUG2(" URI[%S]", fullPath);
CleanupStack::PopAndDestroy(fullPath);
}
if (attributeId & EMPXMediaGeneralDrive)
{
aMedia.SetTextValueL(KMPXMediaGeneralDrive, driveUnit.Name());
}
if (attributeId & EMPXMediaGeneralFlags)
{
TUint32 dbFlags(aRecord.ColumnInt64(EPlaylistDbFlag));
TInt driveId = driveUnit & KMPXMediaGeneralFlagsDriveInfo; // 5 bits
aMedia.SetTObjectValueL<TUint>(KMPXMediaGeneralFlags, dbFlags | driveId);
}
}
if (attributeId & EMPXMediaGeneralSynchronized)
{
aMedia.SetTObjectValueL<TBool>(KMPXMediaGeneralSynchronized,
aRecord.ColumnInt(EPlaylistSync));
}
if (attributeId & EMPXMediaGeneralCount)
{
// make sure the PlaylistSongs query is executed after all fields
// from the current record have been processed, otherwise the recordset
// may point to something else
countRequested = ETrue;
}
if (attributeId & EMPXMediaGeneralDate)
{
// convert the time from the internal DB string format
// to the int64 format used by TTime
aMedia.SetTObjectValueL<TInt64>(KMPXMediaGeneralDate,
MPXDbCommonUtil::DesToTTimeL(
MPXDbCommonUtil::GetColumnTextL(aRecord, EPlaylistTime)).Int64());
}
if ( attributeId & EMPXMediaGeneralDuration )
{
// make sure the PlaylistSongs query is executed after all fields
// from the current record have been processed, otherwise the recordset
// may point to something else
durationRequested = ETrue;
}
} // end if contentId == KMPXMediaIdGeneral
} // end for
TInt plSongCount(0);
TInt plSongDuration(0);
if (countRequested)
{
if (driveId >= 0)
{
//valid disk
iObserver.HandlePlaylistInfoL(playlistId, plSongCount, plSongDuration);
}
aMedia.SetTObjectValueL<TInt>(KMPXMediaGeneralCount,
plSongCount );
MPX_DEBUG1(" EMPXMediaGeneralCount");
MPX_DEBUG2(" Count[%d]", plSongCount);
}
if (durationRequested)
{
aMedia.SetTObjectValueL<TInt>(KMPXMediaGeneralDuration, plSongDuration);
MPX_DEBUG1(" EMPXMediaGeneralDuration");
MPX_DEBUG2(" Duration[%d]", plSongDuration);
}
aMedia.SetTObjectValueL<TMPXGeneralType>(KMPXMediaGeneralType, EMPXItem);
aMedia.SetTObjectValueL<TMPXGeneralCategory>(KMPXMediaGeneralCategory, EMPXPlaylist);
}
// ----------------------------------------------------------------------------
// CMPXDbPlaylist::GetPlaylistRecordL
// ----------------------------------------------------------------------------
//
RSqlStatement CMPXDbPlaylist::GetPlaylistRecordL(
TUint32 aPlaylistId)
{
MPX_FUNC("CMPXDbPlaylist::GetPlaylistRecordL");
return iDbManager.ExecuteSelectQueryL(KQueryPlaylistGet, aPlaylistId);
}
// ----------------------------------------------------------------------------
// CMPXDbPlaylist::DoAddPlaylistL
// ----------------------------------------------------------------------------
//
TUint32 CMPXDbPlaylist::DoAddPlaylistL(
const CMPXMedia& aMedia,
TInt aDriveId)
{
MPX_FUNC("CMPXDbPlaylist::DoAddPlaylistL");
const TDesC& playlistName(aMedia.ValueText(KMPXMediaGeneralTitle));
const TDesC& playlistUri(aMedia.ValueText(KMPXMediaGeneralUri));
TUint32 playlistId(MPXDbCommonUtil::GenerateUniqueIdL(iDbManager.Fs(), EMPXPlaylist, playlistUri, EFalse));
const CMPXMediaArray* mediaArray = aMedia.Value<CMPXMediaArray>(KMPXMediaArrayContents);
if( !mediaArray )
{
User::Leave( KErrNoMemory );
}
// add the songs to the PlaylistSongs table
TInt count(mediaArray->Count());
for (TInt i = 0; i < count; ++i)
{
iPlaylistSongs->AddSongL(playlistId, i, *mediaArray->AtL(i), aDriveId);
}
// determine the value of DbFlag
TUint dbflags(0);
if (aMedia.IsSupported(KMPXMediaGeneralFlags))
{
TUint flag(aMedia.ValueTObjectL<TUint>(KMPXMediaGeneralFlags));
if (flag & KMPXMediaGeneralFlagsSetOrUnsetBit )
{
// Set flag
dbflags |= flag;
MPX_DEBUG2(" GeneralFlags[%b]", dbflags);
}
}
// add playlist record
HBufC* time = MPXDbCommonUtil::CurrentTimeDesLC();
HBufC* name = MPXDbCommonUtil::ProcessSingleQuotesLC(playlistName);
HBufC* uri = MPXDbCommonUtil::ProcessSingleQuotesLC(playlistUri);
TPtrC uriPtr(uri->Mid(KMCPathStartPos));
TPtrC namePtr(name->Left(KMCMaxTextLen));
iDbManager.ExecuteQueryL(aDriveId, KQueryPlaylistInsert, playlistId, &namePtr,
&uriPtr, MPXDbCommonUtil::GetVolIdMatchDriveIdL(iDbManager.Fs(), aDriveId),
dbflags, time);
CleanupStack::PopAndDestroy(uri);
CleanupStack::PopAndDestroy(name);
CleanupStack::PopAndDestroy(time);
return playlistId;
}
// ----------------------------------------------------------------------------
// CMPXDbPlaylist::DoUpdatePlaylistL
// ----------------------------------------------------------------------------
//
void CMPXDbPlaylist::DoUpdatePlaylistL(
TUint32 aPlaylistId,
const CMPXMedia& aMedia,
TInt aDriveId,
CMPXMessage& aMessage)
{
MPX_FUNC("CMPXDbPlaylist::DoUpdatePlaylistL");
// construct the criteria array
const TArray<TMPXAttribute> attributes = aMedia.Attributes();
CDesCArrayFlat* criteriaArray = new (ELeave) CDesCArrayFlat(attributes.Count());
CleanupStack::PushL(criteriaArray);
TInt attrCount(attributes.Count());
for (TInt index = 0; index < attrCount; ++index)
{
TInt contentId(attributes[index].ContentId());
TUint attributeId(attributes[index].AttributeId());
switch(contentId)
{
case KMPXMediaIdGeneral:
{
if (attributeId & EMPXMediaGeneralTitle)
{
MPXDbCommonUtil::AddSqlCriterionL(*criteriaArray, KCriterionPlaylistTitle,
aMedia.ValueText(KMPXMediaGeneralTitle));
}
if (attributeId & EMPXMediaGeneralUri)
{
const TDesC& uri(aMedia.ValueText (KMPXMediaGeneralUri));
// determine if we are changing URI of an existing playlist.
// if so, update playlist URI + its Id
TUint32 newId(MPXDbCommonUtil::GenerateUniqueIdL(iDbManager.Fs(), EMPXPlaylist, uri, EFalse));
if (aPlaylistId != newId)
{
aMessage.SetTObjectValueL<TMPXItemId>(KMPXMessageMediaGeneralId, newId);
aMessage.SetTObjectValueL<TMPXItemId>(KMPXMessageMediaDeprecatedId, aPlaylistId);
// Change event handling for renaming a playlist should be like a song
// The item focus should goto the new name of the playlist
// to-do: this should be abstracted from the plugin. framework should
// have enough info to deal with this scenario, if not, add more
// info in the message passing back to framework
aMessage.SetTObjectValueL<TMPXGeneralCategory>(KMPXMessageMediaGeneralCategory,
EMPXSong);
// update the PlaylistSongs to reflect playlist id change
iPlaylistSongs->UpdateSongsL(aPlaylistId, newId);
// this takes care of processing the single quotes in the URI
MPXDbCommonUtil::AddSqlCriterionL(*criteriaArray, KCriterionPlaylistUri,
uri.Mid(KMCPathStartPos));
MPXDbCommonUtil::AddSqlCriterionL(*criteriaArray, KCriterionPlaylistVolumeId,
MPXDbCommonUtil::GetVolIdMatchDriveIdL(iDbManager.Fs(), TDriveUnit(uri)));
MPXDbCommonUtil::AddSqlCriterionL(*criteriaArray, KCriterionPlaylistUniqueId,
newId);
}
}
if (attributeId & EMPXMediaGeneralSynchronized)
{
MPXDbCommonUtil::AddSqlCriterionL(*criteriaArray, KCriterionPlaylistSync,
aMedia.ValueTObjectL<TBool>(KMPXMediaGeneralSynchronized));
}
}
break;
default:
break;
} // end switch
} // end for
// update the time field to the current time
HBufC* time = MPXDbCommonUtil::CurrentTimeDesLC();
MPXDbCommonUtil::AddSqlCriterionL(*criteriaArray, KCriterionPlaylistTime, *time);
CleanupStack::PopAndDestroy(time);
// construct a string from all criteria
HBufC* criteria = MPXDbCommonUtil::StringFromArrayLC(*criteriaArray, KMCCommaSign);
// execute the query
iDbManager.ExecuteQueryL(aDriveId, KQueryPlaylistUpdate, criteria, aPlaylistId);
CleanupStack::PopAndDestroy(criteria);
CleanupStack::PopAndDestroy(criteriaArray);
}
// ----------------------------------------------------------------------------
// CMPXDbPlaylist::UpdatePlaylistsForSongL
// ----------------------------------------------------------------------------
//
void CMPXDbPlaylist::UpdatePlaylistsForSongL(
TUint32 aSongId,
CMPXMessageArray* aItemChangedMessages, TBool& aSongInPlaylists)
{
MPX_FUNC("CMPXDbPlaylist::UpdatePlaylistsForSongL");
aSongInPlaylists = EFalse;
if (aItemChangedMessages)
{
// get all playlists for the song
RSqlStatement recordset(iDbManager.ExecuteSelectQueryL(KQueryPlaylistGetForSong, aSongId));
CleanupClosePushL(recordset);
// ignore the errors
while (recordset.Next() == KSqlAtRow)
{
aSongInPlaylists = ETrue;
// add item changed messages for all of them
MPXDbCommonUtil::AddItemChangedMessageL(*aItemChangedMessages,
recordset.ColumnInt64(KMPXTableDefaultIndex), EMPXItemModified,
EMPXPlaylist, KDBPluginUid);
}
CleanupStack::PopAndDestroy(&recordset);
}
if (aSongInPlaylists)
{
// update the time for all playlists that contain this song
HBufC* time = MPXDbCommonUtil::CurrentTimeDesLC();
iDbManager.ExecuteQueryL (KDbManagerAllDrives,
KQueryPlaylistUpdateTimeForSong, time, aSongId);
CleanupStack::PopAndDestroy (time);
}
}
// ----------------------------------------------------------------------------
// CMPXDbPlaylist::CreateTableL
// ----------------------------------------------------------------------------
//
void CMPXDbPlaylist::UpdatePlaylistTimeL(
TUint32 aPlaylistId,
TInt aDrive)
{
MPX_FUNC("CMPXDbPlaylist::UpdatePlaylistTimeL");
HBufC* time = MPXDbCommonUtil::CurrentTimeDesLC();
iDbManager.ExecuteQueryL(aDrive, KQueryPlaylistUpdateTime, time, aPlaylistId);
CleanupStack::PopAndDestroy(time);
}
// ----------------------------------------------------------------------------
// CMPXDbPlaylist::GetDrivePlaylistDuration
// ----------------------------------------------------------------------------
//
TInt CMPXDbPlaylist::GetDrivePlaylistDuration(TUint32 /*aPlaylistId*/)
{
return 0;
}
// ----------------------------------------------------------------------------
// CMPXDbPlaylist::CreateTableL
// ----------------------------------------------------------------------------
//
void CMPXDbPlaylist::CreateTableL(
RSqlDatabase& aDatabase,
TBool /* aCorruptTable */)
{
MPX_FUNC("CMPXDbPlaylist::CreateTableL");
// create the table
User::LeaveIfError(aDatabase.Exec(KPlaylistCreateTable));
// create the index on the Name field
User::LeaveIfError(aDatabase.Exec(KPlaylistNameIndex));
}
// ----------------------------------------------------------------------------
// CMPXDbPlaylist::DropTableL
// ----------------------------------------------------------------------------
//
void CMPXDbPlaylist::DropTableL(
RSqlDatabase& aDatabase)
{
MPX_FUNC("CMPXDbPlaylist::DropTableL");
User::LeaveIfError(aDatabase.Exec(KPlaylistDropTable));
}
// ----------------------------------------------------------------------------
// CMPXDbPlaylist::CheckTableL
// ----------------------------------------------------------------------------
//
TBool CMPXDbPlaylist::CheckTableL(
RSqlDatabase& aDatabase)
{
MPX_FUNC("CMPXDbPlaylist::CheckTableL");
return DoCheckTable(aDatabase, KPlaylistCheckTable);
}
// End of File