/*
* 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: Simple plugin to cache media objects
*
*/
// INCLUDE FILES
#include <e32cmn.h>
#include <mpxcollectionpath.h>
#include <mpxcollectionpluginobserver.h>
#include <mpxcmn.h>
#include <mpxmediageneraldefs.h>
#include <mpxmediacontainerdefs.h>
#include <mpxmediamusicdefs.h>
#include <mpxmediaaudiodefs.h>
#include <mpxmessagegeneraldefs.h>
#include <mpxcollectionmessagedefs.h>
#include <mpxmediacollectiondetaildefs.h>
#include <mpxcollectioncommanddefs.h>
#include <mpxcommandgeneraldefs.h>
#include <mpxmedia.h>
#include <mpxmediaarray.h>
#include <mpxdrmmediautility.h>
#include <mpxmediadrmdefs.h>
#include <mpxlog.h>
#include "mpxinmemoryplugin.h"
// CONSTANTS
const TInt KIMPluginUid = 0x101FFCD8;
// ============================ MEMBER FUNCTIONS ==============================
// ----------------------------------------------------------------------------
// Two-phased constructor.
// ----------------------------------------------------------------------------
//
CMPXInMemoryPlugin* CMPXInMemoryPlugin::NewL()
{
CMPXInMemoryPlugin* p = new (ELeave) CMPXInMemoryPlugin();
CleanupStack::PushL(p);
p->ConstructL();
CleanupStack::Pop(p);
return p;
}
// ----------------------------------------------------------------------------
// Destructor
// ----------------------------------------------------------------------------
//
CMPXInMemoryPlugin::~CMPXInMemoryPlugin()
{
delete iDrmMediaUtility;
// Cleanup Arrays
iTemporaryData.ResetAndDestroy();
iTemporaryData.Close();
iEmbeddedContext.Reset();
iEmbeddedContext.Close();
}
// ----------------------------------------------------------------------------
// Constructor
// ----------------------------------------------------------------------------
//
CMPXInMemoryPlugin::CMPXInMemoryPlugin()
{
}
// ----------------------------------------------------------------------------
// Symbian 2nd phase constructor can leave.
// ----------------------------------------------------------------------------
//
void CMPXInMemoryPlugin::ConstructL()
{
iDrmMediaUtility = CMPXDrmMediaUtility::NewL();
}
// ----------------------------------------------------------------------------
// Navigates to the given path
// ----------------------------------------------------------------------------
//
void CMPXInMemoryPlugin::OpenL(
const CMPXCollectionPath& aPath,
const TArray<TMPXAttribute>& /*aAttrs*/,
CMPXFilter* /*aFilter*/)
{
// Media object to return
RArray<TInt> supportedIds;
CleanupClosePushL(supportedIds);
supportedIds.AppendL(KMPXMediaIdContainer);
supportedIds.AppendL(KMPXMediaIdGeneral);
CMPXMedia* entries=CMPXMedia::NewL(supportedIds.Array());
CleanupStack::PushL(entries);
// Media array for items
CMPXMediaArray* array=CMPXMediaArray::NewL();
CleanupStack::PushL(array);
// Based on Path, what is the embedded client context id?
TInt depth = aPath.Levels();
TBool oneSong = EFalse;
TInt err = KErrNone;
switch( depth )
{
case 1: // should not have anything
{
User::Leave( KErrArgument );
break;
}
case 2: // an item or a playlist
{
TInt context = aPath.Id(1);
TInt contextIndex = iEmbeddedContext.Find( context );
if( contextIndex >= KErrNone )
{
CMPXMedia& media = *iTemporaryData[contextIndex];
TMPXGeneralCategory cat = *media.Value<TMPXGeneralCategory>( KMPXMediaGeneralCategory );
if( cat == EMPXPlaylist )
{
const CMPXMediaArray* plarray = media.Value<CMPXMediaArray>( KMPXMediaArrayContents );
for( TInt i=0; i<plarray->Count(); ++i )
{
CMPXMedia* item = (*plarray)[i];
CMPXMedia* copy = CMPXMedia::NewL(*item);
// item id is the index in the array
copy->SetTObjectValueL<TMPXItemId>( KMPXMediaGeneralId, i );
array->AppendL( copy ); // ownership x-fer
}
// Insert dummy media objects if the "specified" count is > actual
// number of media objects
TInt count(0);
if( media.IsSupported(KMPXMediaArrayCount) )
{
count = *media.Value<TInt>(KMPXMediaArrayCount);
}
if( count > 0 && count > plarray->Count() )
{
for( TInt i=plarray->Count(); i<count; ++i )
{
// Insert dummies
CMPXMedia* copy = CMPXMedia::NewL();
copy->SetTObjectValueL<TMPXItemId>( KMPXMediaGeneralId, i );
copy->SetTObjectValueL( KMPXMediaGeneralType,
EMPXItem );
copy->SetTObjectValueL( KMPXMediaGeneralCategory,
EMPXSong );
array->AppendL( copy ); // ownership x-fer
}
}
// Set the title for the playlist
//
if( media.IsSupported( KMPXMediaGeneralTitle ) )
{
const TDesC& title = media.ValueText( KMPXMediaGeneralTitle );
entries->SetTextValueL( KMPXMediaGeneralTitle,
title );
}
}
else // assume it is an item then
{
// Set one song to true
oneSong = ETrue;
}
}
else
{
err = KErrNotFound;
}
break;
}
case 3: // item in a playlist
{
oneSong = ETrue;
break;
}
default:
break;
}
// Set array if not one song
if( !oneSong )
{
entries->SetCObjectValueL(KMPXMediaArrayContents,array);
entries->SetTObjectValueL(KMPXMediaArrayCount,
array->Count());
entries->SetTObjectValueL( KMPXMediaGeneralType,
EMPXGroup );
entries->SetTObjectValueL( KMPXMediaGeneralCategory,
EMPXPlaylist );
}
else
{
entries->SetTObjectValueL( KMPXMediaGeneralType,
EMPXItem );
entries->SetTObjectValueL( KMPXMediaGeneralCategory,
EMPXSong );
}
if(oneSong)
{
iObs->HandleOpen(const_cast<CMPXCollectionPath*>(&aPath), err );
}
else
{
entries->SetCObjectValueL( KMPXMediaGeneralContainerPath,
const_cast<CMPXCollectionPath*>(&aPath) );
iObs->HandleOpen(entries, err );
}
CleanupStack::PopAndDestroy(array);
CleanupStack::PopAndDestroy(entries);
CleanupStack::PopAndDestroy(&supportedIds);
}
// ----------------------------------------------------------------------------
// Extended properties of the current file (async)
// ----------------------------------------------------------------------------
//
void CMPXInMemoryPlugin::MediaL (
const CMPXCollectionPath& aPath,
const TArray<TMPXAttribute>& aAttrs,
const TArray<TCapability>& /*aCaps*/,
CMPXAttributeSpecs* /*aSpecs*/)
{
RArray<TInt> supportedIds;
CleanupClosePushL(supportedIds);
supportedIds.AppendL(KMPXMediaIdGeneral);
CMPXMedia* entries=CMPXMedia::NewL(supportedIds.Array());
CleanupStack::PopAndDestroy(&supportedIds);
CleanupStack::PushL(entries);
// Based on Path, what is the embedded client context id?
//
TInt err = KErrNone;
TInt depth = aPath.Levels();
switch( depth )
{
case 2: // Playlist / Song level
case 3: // Song in a playlist level, fall through
{
TInt context = aPath.Id(1);
TInt contextIndex = iEmbeddedContext.Find( context );
if( contextIndex >= KErrNone )
{
CMPXMedia& media = *iTemporaryData[contextIndex];
TMPXGeneralCategory cat;
cat = *media.Value<TMPXGeneralCategory>( KMPXMediaGeneralCategory );
// Playlist media
//
if( cat == EMPXPlaylist && depth == 2)
{
// Get
const TDesC& title = media.ValueText( KMPXMediaGeneralTitle );
const TDesC& uri = media.ValueText( KMPXMediaGeneralUri );
// Set
entries->SetTextValueL( KMPXMediaGeneralTitle,
title );
entries->SetTextValueL( KMPXMediaGeneralUri,
uri );
entries->SetTObjectValueL<TUid>(KMPXMediaGeneralCollectionId,
TUid::Uid(KIMPluginUid) );
}
// Item in a playlist media
//
else if( cat == EMPXPlaylist && depth == 3 )
{
const CMPXMediaArray* plarray = media.Value<CMPXMediaArray>(
KMPXMediaArrayContents );
TInt selection = aPath.Id( 2 );
TInt count = plarray->Count();
if( selection < count )
{
*entries = *(*plarray)[selection];
entries->SetTObjectValueL<TUid>(KMPXMediaGeneralCollectionId,
TUid::Uid(KIMPluginUid) );
}
else
{
// Bounds check
err = KErrArgument;
}
}
// Otherwise, assume it is a song
//
else // cat == song/image/video/etc
{
*entries = media;
entries->SetTObjectValueL<TUid>(KMPXMediaGeneralCollectionId,
TUid::Uid(KIMPluginUid) );
}
}
break;
}
default:
{
// Return Nothing because a MediaL at this depth contains nothing
break;
}
}
//
for (TInt i=aAttrs.Count();--i>=0;)
{
if (aAttrs[i]==KMPXMediaGeneralPath)
{
entries->SetCObjectValueL(KMPXMediaGeneralPath,
const_cast<CMPXCollectionPath*>(&aPath));
break;
}
}
// Full metadata is not available from this plugin
entries->SetTObjectValueL( KMPXMediaColDetailMediaNotAvailable,
ETrue );
//
iObs->HandleMedia(entries, err );
CleanupStack::PopAndDestroy(entries);
}
// ----------------------------------------------------------------------------
// Cancel outstanding request
// ----------------------------------------------------------------------------
//
void CMPXInMemoryPlugin::CancelRequest()
{
}
// ----------------------------------------------------------------------------
// Executes a command on the selected collection
// ----------------------------------------------------------------------------
//
void CMPXInMemoryPlugin::CommandL(TMPXCollectionCommand /*aCmd*/, TInt /*aArg*/)
{
}
// ----------------------------------------------------------------------------
// Executes a command on the selected collection
// ----------------------------------------------------------------------------
//
void CMPXInMemoryPlugin::CommandL(CMPXCommand& aCmd)
{
if (!aCmd.IsSupported(TMPXAttribute(KMPXCommandContentIdGeneral, EMPXCommandGeneralId)))
{
User::Leave(KErrArgument);
}
TMPXCommandId commandId =
*aCmd.Value<TMPXCommandId>(
TMPXAttribute(KMPXCommandContentIdGeneral, EMPXCommandGeneralId));
TBool syncOp(EFalse);
if( aCmd.IsSupported(KMPXCommandGeneralDoSync) )
{
syncOp = *aCmd.Value<TBool>(KMPXCommandGeneralDoSync);
}
// Handle each operation
//
switch( commandId )
{
case KMPXCommandIdCollectionAdd:
{
DoAddL( *aCmd.Value<CMPXMedia>(KMPXCommandColAddMedia) );
break;
}
case KMPXCommandIdCollectionSet:
{
DoSetL( *aCmd.Value<CMPXMedia>(KMPXCommandColSetMedia) );
break;
}
default:
{
User::Leave(KErrNotSupported);
}
}
// Complete Async operations
//
if( !syncOp )
{
iObs->HandleCommandComplete( NULL, KErrNone );
}
}
// ----------------------------------------------------------------------------
// Adds item(s) to the collection
// ----------------------------------------------------------------------------
//
void CMPXInMemoryPlugin::AddL(
const CMPXMedia& aNewMedia)
{
DoAddL( aNewMedia );
}
// ----------------------------------------------------------------------------
// Remove by collection path
// ----------------------------------------------------------------------------
//
void CMPXInMemoryPlugin::RemoveL(const CMPXCollectionPath& aPath )
{
(void) aPath;
}
// ----------------------------------------------------------------------------
// Remove an item or items under a group from the collection
// ----------------------------------------------------------------------------
//
void CMPXInMemoryPlugin::RemoveL(const CMPXMedia& aMedia)
{
(void)aMedia;
}
// ----------------------------------------------------------------------------
// Sets/updates the media for the item
// ----------------------------------------------------------------------------
//
void CMPXInMemoryPlugin::SetL(
const CMPXMedia& aMedia)
{
DoSetL( aMedia );
}
// ----------------------------------------------------------------------------
// Find based on media properties
// ----------------------------------------------------------------------------
//
void CMPXInMemoryPlugin::FindAllL(const CMPXMedia& aMedia,
const TArray<TMPXAttribute>& aAttrs )
{
(void)aMedia;
(void)aAttrs;
}
// ----------------------------------------------------------------------------
// Find based on media properties
// ----------------------------------------------------------------------------
//
CMPXMedia* CMPXInMemoryPlugin::FindAllSyncL(const CMPXMedia& aMedia,
const TArray<TMPXAttribute>& aAttrs )
{
(void)aMedia;
(void)aAttrs;
User::Leave(KErrNotSupported);
return NULL;
}
// ----------------------------------------------------------------------------
// Find the capabilities of this plugin
// ----------------------------------------------------------------------------
//
TCollectionCapability CMPXInMemoryPlugin::GetCapabilities()
{
return 0; // nothing special supported
}
// ----------------------------------------------------------------------------------------------------------
// Handle change
// ----------------------------------------------------------------------------------------------------------
//
void CMPXInMemoryPlugin::HandleChangeL(const TMPXItemId& aId, TMPXChangeEventType aChange )
{
// Construct the message
//
CMPXMessage* message = CMPXMedia::NewL();
CleanupStack::PushL( message );
// Set attributes
//
message->SetTObjectValueL<TMPXMessageId>(KMPXMessageGeneralId, KMPXMessageIdItemChanged);
message->SetTObjectValueL<TUid>(KMPXMessageCollectionId, TUid::Uid(KIMPluginUid));
message->SetTObjectValueL<TMPXChangeEventType>(KMPXMessageChangeEventType, aChange);
message->SetTObjectValueL<TMPXItemId>(KMPXMessageMediaGeneralId, aId);
// Callback to observer and destroy
//
iObs->HandleMessage( *message );
CleanupStack::PopAndDestroy( message );
}
// ----------------------------------------------------------------------------
// Adds item(s) to the collection
// ----------------------------------------------------------------------------
//
void CMPXInMemoryPlugin::DoAddL(
const CMPXMedia& aNewMedia)
{
TInt context = *aNewMedia.Value<TInt>( TMPXAttribute(KMPXMediaIdGeneral,
EMPXMediaGeneralId ) );
// Only 1 set of data per embedded context
TInt index = iEmbeddedContext.Find( context );
if( index != KErrNotFound )
{
iEmbeddedContext.Remove( index );
delete iTemporaryData[index];
iTemporaryData.Remove( index );
iEmbeddedContext.Compress();
iTemporaryData.Compress();
}
// Push onto list
iEmbeddedContext.AppendL( context );
CMPXMedia* copy = CMPXMedia::NewL();
*copy = aNewMedia;
iTemporaryData.AppendL( copy ); // ownership transferred.
}
// ----------------------------------------------------------------------------
// Sets/updates the media for the item
// ----------------------------------------------------------------------------
//
void CMPXInMemoryPlugin::DoSetL(
const CMPXMedia& aMedia)
{
MPX_DEBUG1("CMPXInMemoryPlugin::DoSetL <---");
if( !aMedia.IsSupported(KMPXMediaGeneralId) )
{
User::Leave( KErrArgument );
}
TInt context = *aMedia.Value<TMPXItemId>(KMPXMediaGeneralId);
TInt index = iEmbeddedContext.Find( context );
MPX_DEBUG2("CMPXInMemoryPlugin::DoSetL index %i", index);
if( index != KErrNotFound )
{
TMPXAttribute att( KMPXMediaArrayContents );
// Make sure it has a media array
//
if( aMedia.IsSupported( att ) )
{
MPX_DEBUG1("CMPXInMemoryPlugin::DoSetL 1");
// Grab the 2 media arrays
//
CMPXMediaArray* currentMedia =
const_cast<CMPXMediaArray*>(iTemporaryData[index]->Value<CMPXMediaArray>(att));
const CMPXMediaArray* newMedia = aMedia.Value<CMPXMediaArray>(att);
MPX_DEBUG1("CMPXInMemoryPlugin::DoSetL 2");
// Copy all entries from newMedia into currentMedia
//
TInt newCount = newMedia->Count();
for( TInt i=0; i<newCount; ++i )
{
MPX_DEBUG1("CMPXInMemoryPlugin::DoSetL 3");
CMPXMedia* copy = CMPXMedia::NewL(*(*newMedia)[i]);
CleanupStack::PushL( copy );
// If the item contains an item ID, we use it as an index to insert
// into the array, otherwise, append item to the end
//
MPX_DEBUG1("CMPXInMemoryPlugin::DoSetL 4");
if( copy->IsSupported(KMPXMediaGeneralId) )
{
TInt index = *copy->Value<TMPXItemId>(KMPXMediaGeneralId);
MPX_DEBUG2("CMPXInMemoryPlugin::DoSetL index count %i", index);
// index is 0th based, like an array
//
TInt currentCount = currentMedia->Count();
if( index > currentCount )
{
// Fill in blanks then append the item we want
//
for( TInt j=currentCount; j<index; ++j )
{
CMPXMedia* blank = CMPXMedia::NewL();
CleanupStack::PushL( blank );
currentMedia->AppendL( blank ); // ownership xfer
CleanupStack::Pop( blank );
}
currentMedia->AppendL( copy ); // ownership xfer
}
else
{
// Replace item at index with this new version
//
currentMedia->Remove(index);
currentMedia->Insert( copy, index ); // ownership xfer
}
}
else
{
currentMedia->AppendL( copy ); // ownership xfer
}
MPX_DEBUG1("CMPXInMemoryPlugin::DoSetL 5");
CleanupStack::Pop(copy);
}
// Set the new array into the media
//
MPX_DEBUG1("CMPXInMemoryPlugin::DoSetL 6");
iTemporaryData[index]->SetCObjectValueL(att, currentMedia );
// Tell collection client context that something was added
//
MPX_DEBUG1("CMPXInMemoryPlugin::DoSetL 7");
HandleChangeL( context, EMPXItemInserted );
MPX_DEBUG1("CMPXInMemoryPlugin::DoSetL 8");
}
}
else
{
MPX_DEBUG1("CMPXInMemoryPlugin::DoSetL KErrArgument");
User::Leave( KErrArgument );
}
MPX_DEBUG1("CMPXInMemoryPlugin::DoSetL --->");
}
// End of file