/*
* 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: Controls playback via plug-ins
*
*/
#include <featmgr.h>
#include <mpxprivatecrkeys.h>
#include <mpxlog.h>
#include <mpxtaskqueue.h>
#include <mpxmediageneraldefs.h>
#include <mpxmediamusicdefs.h>
#include <mpxmedia.h>
#include <mpxcommonframeworkdefs.h>
#include <mpxcommandgeneraldefs.h>
#include <mpxplaybackcommanddefs.h>
#include <mpxcollectionpath.h>
#include <mpxattributespecs.h>
#include <mpxmessagepluginupdatedefs.h>
#include <mpxplaybackpluginversion2.h>
#include <mpxcmn.h>
#include <caf/caferr.h>
#include <mpxmediageneralextdefs.h>
#include "mpxplaybacksettings.h"
#include "mpxautoresumehandler.h"
#include "mpxplaybackcommandbuffer.h"
#include "mpxplaybackactiveengineobserver.h"
#include "mpxplaybackinitializer.h"
#include "mpxplaybackengine.h"
#include "mpxplaybackmediahelper.h"
#include "mpxplaybackdummymediaobserver.h"
// CONSTANTS
const TInt KMPXSmallVolumeIncrement = 5;
const TInt KMPXLargeVolumeIncrement = 10;
const TInt KPercentMultiplier = 100;
_LIT(KWmaExtension, ".wma");
_LIT(KRaExtension, ".ra");
// ============================ MEMBER FUNCTIONS ==============================
// ----------------------------------------------------------------------------
// Two-phased constructor.
// ----------------------------------------------------------------------------
//
EXPORT_C CMPXPlaybackEngine* CMPXPlaybackEngine::NewL(
CMPXPluginMonitor& aPluginMonitor,
MMPXPlaybackActiveEngineObserver& aObserver,
MMPXClientlistObserver* aClientListObserver,
const TUid& aModeId)
{
CMPXPlaybackEngine* p=new(ELeave)CMPXPlaybackEngine(aPluginMonitor,
aObserver, aModeId);
CleanupStack::PushL(p);
p->ConstructL(aClientListObserver);
CleanupStack::Pop(p);
return p;
}
// ----------------------------------------------------------------------------
// Two-phased constructor.
// ----------------------------------------------------------------------------
//
EXPORT_C CMPXPlaybackEngine* CMPXPlaybackEngine::NewL(
CMPXPluginMonitor& aPluginMonitor,
MMPXPlaybackActiveEngineObserver& aObserver,
MMPXClientlistObserver* aClientListObserver,
const TUid& aModeId,
const TInt aCategory)
{
CMPXPlaybackEngine* p=new(ELeave)CMPXPlaybackEngine(aPluginMonitor,
aObserver, aModeId, aCategory);
CleanupStack::PushL(p);
p->ConstructL(aClientListObserver);
CleanupStack::Pop(p);
return p;
}
// ----------------------------------------------------------------------------
// Constructor.
// ----------------------------------------------------------------------------
//
CMPXPlaybackEngine::CMPXPlaybackEngine(
CMPXPluginMonitor& aPluginMonitor,
MMPXPlaybackActiveEngineObserver& aObserver,
const TUid& aModeId)
: iReflector(*this),
iPluginMonitor(aPluginMonitor),
iItemId(KMPXInvalidItemId),
iPlaySource(EPlayNone),
iAccessPoint(0),
iAccessPointSet(EFalse),
iState(EPbStateNotInitialised),
iNextState(EPbStateNotInitialised),
iPluginState(EPbStateNotInitialised),
iModeId(aModeId),
iObserver(aObserver),
iPreservedState( EPbStateNotInitialised ),
iPreservedPosition( KErrNotFound ),
iSkipping(EFalse),
iPluginUid(KNullUid),
iLastActiveProcess(KNullProcessId),
iLastInactiveProcess(KNullProcessId)
{
iProperties[EPbPropertyVolumeRamp]=KPbFadeInDurationMicroSeconds;
}
// ----------------------------------------------------------------------------
// Constructor.
// ----------------------------------------------------------------------------
//
CMPXPlaybackEngine::CMPXPlaybackEngine(
CMPXPluginMonitor& aPluginMonitor,
MMPXPlaybackActiveEngineObserver& aObserver,
const TUid& aModeId,
const TInt aCategory)
: iReflector(*this),
iPluginMonitor(aPluginMonitor),
iItemId(KMPXInvalidItemId),
iPlaySource(EPlayNone),
iAccessPoint(0),
iAccessPointSet(EFalse),
iState(EPbStateNotInitialised),
iNextState(EPbStateNotInitialised),
iPluginState(EPbStateNotInitialised),
iModeId(aModeId),
iObserver(aObserver),
iPreservedState( EPbStateNotInitialised ),
iPreservedPosition( KErrNotFound ),
iSkipping(EFalse),
iPluginUid(KNullUid),
iLastActiveProcess(KNullProcessId),
iLastInactiveProcess(KNullProcessId),
iCategory(aCategory)
{
iProperties[EPbPropertyVolumeRamp]=KPbFadeInDurationMicroSeconds;
}
// ----------------------------------------------------------------------------
// 2nd phase constructor.
// ----------------------------------------------------------------------------
//
void CMPXPlaybackEngine::ConstructL(MMPXClientlistObserver* aClientListObserver)
{
MPX_FUNC_EX("CMPXPlaybackEngine::ConstructL");
iClientList=CMPXClientList::NewL(aClientListObserver);
iPluginHandler=CMPXPlaybackPluginHandler::NewL(iPluginMonitor, *this, *this);
iCmdBuffer=CMPXPlaybackCmdBuffer::NewL(*this);
iProgressTimer=CHeartbeat::NewL(CActive::EPriorityStandard);
iSeekTimer=CPeriodic::NewL(CActive::EPriorityStandard);
iAccessoryObs=CMPXAccessoryObserver::NewL(*this);
iAutoResumeHandler = CMPXAutoResumeHandler::NewL(*this, EFalse);
iPlaybackSettings = CMPXPlaybackSettings::NewL();
iTaskQueue = CMPXActiveTaskQueue::NewL();
FeatureManager::InitializeLibL();
#if defined(__HIGH_RESOLUTION_VOLUME)
// Intialise volume level increment based on the accessory plugged in.
SetVolumeIncrement( iAccessoryObs->AccessoryModeL() );
#else
iVolumeIncrement = KMPXLargeVolumeIncrement;
#endif
iMediaHelper = CMPXPlaybackMediaHelper::NewL( *this );
iDummyMediaObserver = new(ELeave) CMPXPlaybackDummyMediaObserver();
// Select local plugin by default if none selected
iPluginHandler->SelectPlayersL( EPbLocal );
iInitVolume = ETrue;
#if defined(__HIGH_RESOLUTION_VOLUME)
iVolRoundedUp = EFalse;
#endif
iPluginHandler->Plugin()->PropertyL( EPbPropertyVolume );
}
// ----------------------------------------------------------------------------
// Destructor
// ----------------------------------------------------------------------------
//
EXPORT_C CMPXPlaybackEngine::~CMPXPlaybackEngine()
{
MPX_FUNC_EX("CMPXPlaybackEngine::~CMPXPlaybackEngine");
if (iPluginHandler->Plugin())
{
iPluginHandler->Plugin()->CancelRequest();
}
DoClose();
if (iTaskQueue)
{
delete iTaskQueue;
}
if (iProgressTimer)
{
delete iProgressTimer;
}
if (iSeekTimer)
{
delete iSeekTimer;
}
FeatureManager::UnInitializeLib();
iFile.Close();
delete iCmdBuffer;
delete iAccessoryObs;
delete iAutoResumeHandler;
delete iPluginHandler;
delete iClientList;
delete iPlaybackSettings;
delete iInitializer;
iMediaAttrs.Close();
delete iMediaHelper;
delete iDummyMediaObserver;
#ifdef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API
iFile64.Close();
#endif // SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API
}
// ----------------------------------------------------------------------------
// Initialises from collection
// ----------------------------------------------------------------------------
//
EXPORT_C void CMPXPlaybackEngine::InitL(
const CMPXCollectionPlaylist& aPlaylist,
TBool aPlay )
{
MPX_FUNC_EX("CMPXPlaybackEngine::InitL");
iPluginUid = KNullUid; // Reset plugin uid for current item
iInitNext = aPlaylist.PreInitPlugin();
if ( iInitNext )
{
if ( !iInitializer )
{
iInitializer=CMPXPlaybackInitializer::NewL(*this, *iMediaHelper);
}
iInitializer->Close();
}
HandleCloseL();
iPlaySource=EPlayFromCollection;
iPlaylist=CMPXCollectionPlaylist::NewL(aPlaylist, this);
CMPXCollectionPlaylist::TRepeatMode repeatmode =
static_cast<CMPXCollectionPlaylist::TRepeatMode>(
iProperties[EPbPropertyRepeatMode]);
iPlaylist->SetRepeatMode(repeatmode);
// if current index is not 0, play the selected item, otherwise play any one
iPlaylist->SetShuffleL(iProperties[EPbPropertyRandomMode],
iPlaylist->Index()!=-1);
iSkipping = EFalse;
if ( aPlay )
{
if ( iPlaylist->Count() > 0 )
{
iNextState=EPbStateNotInitialised;
MediaFromCollectionL();
}
}
else
{
if ( iPlaylist->Count() > 0 )
{
iState = EPbStateStopped;
}
else
{
iState = EPbStateNotInitialised;
}
iAutoResumeHandler->HandlePlaybackStateChange(iState);
iClientList->SendMsgL(
TMPXPlaybackMessage(TMPXPlaybackMessage::EStateChanged,iState));
iNextState = iState;
//update now playing view
iClientList->SendMsgL(TMPXPlaybackMessage(
TMPXPlaybackMessage::EPlaylistUpdated));
iClientList->SendMsgL(
TMPXPlaybackMessage(
TMPXPlaybackMessage::EInitializeComplete,
0,
EFalse));
iPluginUid = iPluginHandler->Plugin()->Uid();
RArray<TMPXAttribute> dummy;
CleanupClosePushL( dummy );
dummy.AppendL( KMPXMediaGeneralUri ); // dummy attribute to get
iPlaylist->MediaL( dummy.Array(), *iDummyMediaObserver);
CleanupStack::PopAndDestroy( &dummy );
}
}
// ----------------------------------------------------------------------------
// Initialises from URI
// ----------------------------------------------------------------------------
//
EXPORT_C void CMPXPlaybackEngine::InitL(const TDesC& aUri,const TDesC8& aType)
{
MPX_FUNC_EX("CMPXPlaybackEngine::InitL(const TDesC& aUri,const TDesC8& aType)");
MPX_DEBUG2("CMPXPlaybackEngine::InitL(%S)", &aUri);
iPluginUid = KNullUid; // Reset plugin uid for current item
iInitNext=EFalse;
HandleCloseL();
iPlaySource=EPlayFromUri;
iNextState=EPbStateNotInitialised;
delete iUri;
iUri = NULL;
iUri=aUri.AllocL();
iItemId = KMPXInvalidItemId;
TRAPD( err, InitL(&aUri,&aType,NULL) );
if ( KErrNotFound == err || KErrPathNotFound == err )
{
// Mark item as Invalid
MarkItemInvalid( ETrue );
User::Leave( err );
}
}
// ----------------------------------------------------------------------------
// Initialises from file.
// ----------------------------------------------------------------------------
//
EXPORT_C void CMPXPlaybackEngine::InitL(const RFile& aFile)
{
MPX_FUNC_EX("CMPXPlaybackEngine::InitL(const RFile& aFile)");
iPluginUid = KNullUid; // Reset plugin uid for current item
iInitNext=EFalse;
HandleCloseL();
iPlaySource=EPlayFromFile;
iNextState=EPbStateNotInitialised;
iFile.Duplicate(aFile);
TRAPD( err, InitL(NULL,NULL,&iFile) );
if ( KErrNotFound == err )
{
// Mark item as Invalid
MarkItemInvalid( ETrue );
User::Leave( err );
}
}
// ----------------------------------------------------------------------------
// Initialises from URI
// ----------------------------------------------------------------------------
//
EXPORT_C void CMPXPlaybackEngine::InitStreamingL(const TDesC& aUri, const TDesC8& aType, const TInt aAccessPoint)
{
MPX_FUNC_EX("CMPXPlaybackEngine::InitStreamingL(const TDesC& aUri, const TInt aAccessPoint)");
MPX_DEBUG4("CMPXPlaybackEngine::InitStreamingL(%S), (%s), (%d)", &aUri, &aType, aAccessPoint);
iPluginUid = KNullUid; // Reset plugin uid for current item
iInitNext=EFalse;
HandleCloseL();
iPlaySource=EPlayFromUri;
iNextState=EPbStateNotInitialised;
delete iUri;
iUri = NULL;
iUri=aUri.AllocL();
iItemId = KMPXInvalidItemId;
iAccessPoint = aAccessPoint;
iAccessPointSet = ETrue;
TRAPD( err, InitL(&aUri,&aType,NULL,aAccessPoint) );
if ( KErrNotFound == err || KErrPathNotFound == err )
{
// Mark item as Invalid
MarkItemInvalid( ETrue );
User::Leave( err );
}
}
// ----------------------------------------------------------------------------
// Initialises from file.
// ----------------------------------------------------------------------------
//
EXPORT_C void CMPXPlaybackEngine::InitStreamingL(const RFile& aFile, const TInt aAccessPoint)
{
MPX_FUNC_EX("CMPXPlaybackEngine::InitStreamingL(const RFile& aFile, const TInt aAccessPoint)");
iPluginUid = KNullUid; // Reset plugin uid for current item
iInitNext=EFalse;
HandleCloseL();
iPlaySource=EPlayFromFile;
iNextState=EPbStateNotInitialised;
iFile.Duplicate(aFile);
iAccessPoint = aAccessPoint;
iAccessPointSet = ETrue;
TRAPD( err, InitL(NULL,NULL,&iFile,aAccessPoint));
if ( KErrNotFound == err )
{
// Mark item as Invalid
MarkItemInvalid( ETrue );
User::Leave( err );
}
}
// ----------------------------------------------------------------------------
// Cancels all outsatnding calls (tasks): plug-in should only have one
// outstanding so that is canceled; the tasks are deleted and removed from the
// queue
// ----------------------------------------------------------------------------
//
EXPORT_C void CMPXPlaybackEngine::CancelRequests()
{
MPX_FUNC_EX("CMPXPlaybackEngine::CancelRequests()");
CMPXPlaybackPlugin* p(iPluginHandler->Plugin());
if (iCallback && iTaskQueue->PtrData())
{ // there is outstanding request
p = static_cast<CMPXPlaybackPlugin*>(iTaskQueue->PtrData());
}
if (p)
{
p->CancelRequest();
if (iCallback)
{
iTaskQueue->CompleteTask();
iCallback = NULL;
}
}
if (iPlaylist)
{
iPlaylist->CancelRequest();
}
if (iInitializer)
{
iInitializer->Close();
}
iTaskQueue->CancelRequests();
iMediaHelper->CancelRequests();
}
// ----------------------------------------------------------------------------
// Handle a command
// ----------------------------------------------------------------------------
//
EXPORT_C void CMPXPlaybackEngine::CommandL(TMPXPlaybackCommand aCmd,
TInt aData)
{
MPX_DEBUG2("CMPXPlaybackEngine::CommandL(%d) entering", aCmd);
iClientList->SendMsgL(TMPXPlaybackMessage(
TMPXPlaybackMessage::ECommandReceived,
aCmd,
0));
if (iCmdBuffer->CommandForBuffering(aCmd))
{
// Buffered commands are not valid if there are no items in playlist
TBool cmdOK( ETrue );
if ( iPlaySource == EPlayFromCollection )
{
if ( iPlaylist )
{
cmdOK = ( iPlaylist->Count() > 0 );
}
else
{
cmdOK = EFalse;
}
}
if ( cmdOK )
{
iCmdBuffer->BufferCommandL(aCmd,iNextState,
iProperties[EPbPropertyPosition]);
}
}
else
{
HandleCommandL(aCmd,aData);
}
MPX_DEBUG1("CMPXPlaybackEngine::CommandL() exiting");
}
// ----------------------------------------------------------------------------
// Handle a command
// ----------------------------------------------------------------------------
//
EXPORT_C void CMPXPlaybackEngine::CommandL(
CMPXCommand& aCmd,
const CMPXMessageQueue& aMsgQueue )
{
MPX_FUNC_EX("CMPXPlaybackEngine::CommandL(CMPXCommand& aCmd)");
ASSERT(aCmd.IsSupported(KMPXCommandGeneralId));
TInt id = aCmd.ValueTObjectL<TInt>(KMPXCommandGeneralId);
switch (id)
{
case KMPXCommandIdPlaybackGeneral:
{
ASSERT(aCmd.IsSupported(KMPXCommandPlaybackGeneralType));
TMPXPlaybackCommand cmd = static_cast<TMPXPlaybackCommand>(
aCmd.ValueTObjectL<TInt>(KMPXCommandPlaybackGeneralType));
if ( EPbCmdPlay == cmd ||
EPbCmdPlayPause == cmd ||
EPbCmdStop == cmd)
{
ASSERT(aCmd.IsSupported(KMPXCommandPlaybackGeneralClientPid));
iLastActiveProcess = aCmd.ValueTObjectL<TProcessId>(
KMPXCommandPlaybackGeneralClientPid);
}
else if (EPbCmdStop == cmd)
{
ASSERT(aCmd.IsSupported(KMPXCommandPlaybackGeneralClientPid));
iLastInactiveProcess = aCmd.ValueTObjectL<TProcessId>(
KMPXCommandPlaybackGeneralClientPid);
}
TInt data(0);
if (aCmd.IsSupported(KMPXCommandPlaybackGeneralData))
{
data = aCmd.ValueTObjectL<TInt>(KMPXCommandPlaybackGeneralData);
}
MPX_DEBUG3("CMPXPlaybackEngine::CommandL general command (%d) data %d ",
cmd, data);
// Check if command is to be buffered, if not then handle command directly
TBool noBuffer( EFalse );
if ( aCmd.IsSupported( KMPXCommandPlaybackGeneralNoBuffer ))
{
noBuffer = aCmd.ValueTObjectL<TBool>(
KMPXCommandPlaybackGeneralNoBuffer );
}
if ( noBuffer )
{
HandleCommandL( cmd, data );
}
else
{
// Map to TMPXCommand command
CommandL(cmd, data);
}
break;
}
case KMPXCommandSubscriptionAdd:
{
TInt index( iClientList->Find( aMsgQueue ));
CMPXMediaArray* items(
aCmd.Value<CMPXMediaArray>( KMPXCommandSubscriptionAddItems ));
User::LeaveIfNull(items);
CMPXSubscription* subscription( CMPXSubscription::NewL( *items ));
CleanupStack::PushL(subscription);
iClientList->AddSubscriptionL( index, subscription ); // ownership transferred
CleanupStack::Pop(subscription);
break;
}
case KMPXCommandSubscriptionRemove:
{
TInt index( iClientList->Find( aMsgQueue ));
CMPXMediaArray* items(
aCmd.Value<CMPXMediaArray>( KMPXCommandSubscriptionAddItems ));
User::LeaveIfNull(items);
CMPXSubscription* subscription( CMPXSubscription::NewL( *items ));
CleanupStack::PushL(subscription);
iClientList->RemoveSubscriptionL( index, *subscription );
CleanupStack::PopAndDestroy(subscription);
break;
}
case KMPXCommandSubscriptionRemoveAll:
{
TInt index( iClientList->Find( aMsgQueue ));
iClientList->RemoveAllSubscriptionsL( index );
break;
}
default:
{
// Custom command, so just send to plugin to handle
if ( iPluginHandler->Plugin() )
{
iPluginHandler->Plugin()->CommandL( aCmd );
}
}
}
}
// ----------------------------------------------------------------------------
// Set a property
// ----------------------------------------------------------------------------
//
EXPORT_C void CMPXPlaybackEngine::SetL(TMPXPlaybackProperty aProperty,
TInt aValue)
{
MPX_DEBUG3("-->CMPXPlaybackEngine::SetL(%d, %d)", aProperty, aValue);
if ( aProperty < 0 || aProperty > EPbPropertyNum )
{
MPX_DEBUG1("CMPXPlaybackEngine::SetL(): Invalid Argument");
User::Leave( KErrArgument );
}
switch(aProperty)
{
case EPbPropertyEmbeddedMode:
case EPbPropertyCrossFade:
if ( aProperty < iProperties.Count() )
{
iProperties[aProperty]=aValue;
iClientList->SendMsgL(
TMPXPlaybackMessage(TMPXPlaybackMessage::EPropertyChanged,
aProperty, iProperties[aProperty]));
}
break;
case EPbPropertyVolume:
MPX_DEBUG2( "CMPXPlaybackEngine::SetL EPbPropertyVolume %d", aValue );
if ( aValue >= KPbPlaybackVolumeLevelMin &&
aValue <= KPbPlaybackVolumeLevelMax)
{
iProperties[EPbPropertyMute] = EFalse;
iProperties[aProperty] = aValue;
if ( iPluginHandler->Plugin() )
{
PluginL()->SetL( aProperty, aValue );
}
#if defined(__HIGH_RESOLUTION_VOLUME)
iVolRoundedUp = EFalse;
#endif
}
else
{
User::Leave(KErrArgument);
}
break;
case EPbPropertyMute:
MPX_DEBUG2( "CMPXPlaybackEngine::SetL EPbPropertyMute %d", aValue );
if ( iPluginHandler->Plugin() )
{
PluginL()->SetL( aProperty, aValue );
}
break;
case EPbPropertyRandomMode:
{
MPX_DEBUG2( "CMPXPlaybackEngine::SetL EPbPropertyRandomMode %d", aValue );
TBool randomMode = static_cast<TBool>(aValue);
if( iProperties[EPbPropertyRandomMode] != randomMode )
{
iProperties[EPbPropertyRandomMode] = randomMode;
if (iPlaySource==EPlayFromCollection && iPlaylist)
{
TRAP_IGNORE(iPlaylist->SetShuffleL(randomMode, ETrue));
// Pre-initializer needs to re-copy the new shuffle list
// from the engine
if (iInitializer)
{
iInitializer->Close();
}
}
TRAP_IGNORE(iClientList->SendMsgL(
TMPXPlaybackMessage(TMPXPlaybackMessage::EPropertyChanged,
EPbPropertyRandomMode,
randomMode)));
}
break;
}
case EPbPropertyRepeatMode:
{
MPX_DEBUG2( "CMPXPlaybackEngine::SetL EPbPropertyRepeatMode %d", aValue );
TMPXPlaybackRepeatMode repeat = static_cast<TMPXPlaybackRepeatMode>(aValue);
if( iProperties[EPbPropertyRepeatMode] != repeat )
{
iProperties[EPbPropertyRepeatMode] = repeat;
if (iPlaySource==EPlayFromCollection && iPlaylist)
{
CMPXCollectionPlaylist::TRepeatMode repeatmode =
static_cast<CMPXCollectionPlaylist::TRepeatMode>(
repeat);
iPlaylist->SetRepeatMode(repeatmode);
if (iInitializer)
{
iInitializer->Close();
}
}
TRAP_IGNORE(iClientList->SendMsgL(
TMPXPlaybackMessage(TMPXPlaybackMessage::EPropertyChanged,
EPbPropertyRepeatMode,
repeat)));
}
break;
}
case EPbPropertyPosition:
{
CMPXPlaybackPlugin* pi = PluginL();
if ( pi )
{
MPX_DEBUG2( "CMPXPlaybackEngine::SetL setting position %d", aValue );
iProperties[aProperty] = aValue;
pi->SetL(EPbPropertyPosition, aValue);
}
break;
}
default:
iProperties[aProperty]=aValue;
PluginL()->SetL(aProperty,aValue);
}
MPX_DEBUG3("<--CMPXPlaybackEngine::SetL(%d, %d)", aProperty, aValue);
}
// ----------------------------------------------------------------------------
// Property request
// ----------------------------------------------------------------------------
//
EXPORT_C void CMPXPlaybackEngine::PropertyL(TMPXPlaybackProperty aProperty,
MMPXPlaybackEngineObserver& aCallback)
{
MPX_FUNC_EX("CMPXPlaybackEngine::PropertyL()");
MPX_DEBUG4("CMPXPlaybackEngine::PropertyL 0x%08x cb 0x%08x, prop %d",
this, &aCallback, aProperty);
if (aProperty == EPbPropertyVolume)
{
aCallback.HandleProperty(aProperty,
iProperties[EPbPropertyVolume],
KErrNone);
}
else if (aProperty == EPbPropertyMaxVolume)
{
aCallback.HandleProperty(aProperty,
KPbPlaybackVolumeLevelMax,
KErrNone);
}
else if (aProperty == EPbPropertyRandomMode)
{
TInt random(0);
if ( iPlaylist )
{
random = iPlaylist->Shuffle();
}
else
{
random = iProperties[EPbPropertyRandomMode];
}
aCallback.HandleProperty(aProperty,
random,
KErrNone);
}
else if (aProperty == EPbPropertyRepeatMode)
{
TInt repeat(0);
if ( iPlaylist )
{
repeat = iPlaylist->RepeatMode();
}
else
{
repeat = iProperties[EPbPropertyRepeatMode];
}
aCallback.HandleProperty(aProperty,
repeat,
KErrNone);
}
else if (aProperty == EPbPropertyPosition &&
EPbStateNotInitialised == iPluginState)
{
aCallback.HandleProperty(aProperty,
iProperties[EPbPropertyPosition],
KErrNone);
}
else
{
MPX_DEBUG1("CMPXPlaybackEngine::PropertyL add request to task queue");
iTaskQueue->AddTaskL(EProperty, &aCallback, this, aProperty);
}
}
// ----------------------------------------------------------------------------
// Async call: must be added to task queue
// ----------------------------------------------------------------------------
//
EXPORT_C void CMPXPlaybackEngine::MediaL(
MMPXPlaybackEngineObserver& aCallback,
CBufBase* /*aBuf*/)
{
MPX_DEBUG3("-->CMPXPlaybackEngine::MediaL() aBuf 0x%08x cb 0x%08x", this, &aCallback);
// DEPRECATED
MPX_ASSERT( 0 );
MPX_DEBUG2("<--CMPXPlaybackEngine::MediaL() aBuf 0x%08x", this);
}
// ----------------------------------------------------------------------------
// Async call: must be added to task queue
// ----------------------------------------------------------------------------
//
EXPORT_C void CMPXPlaybackEngine::MediaL(
MMPXPlaybackEngineObserver& aCallback,
const CMPXCommand& aCmd)
{
MPX_DEBUG3("-->CMPXPlaybackEngine::MediaL() aCmd 0x%08x cb 0x%08x", this, &aCallback);
CMPXCommand* cmd( CMPXCommand::NewL( aCmd ) );
CleanupStack::PushL( cmd );
TBool redirect = EFalse;
if (CMPXAttributeSpecs* specs = aCmd.Value<CMPXAttributeSpecs>( KMPXCommandMediaAttributeSpecs ))
{
if (specs->IsSupported(KMPXMediaGeneralExtMediaRedirect))
{
redirect = ETrue;
MPX_DEBUG1("CMPXPlaybackEngine::MediaL - Redirect to Playback Plugin");
}
}
// If redirect is false, pass the cmd to mediahelper class
if ( iPlaySource == EPlayFromCollection && iPlaylist && !redirect)
{
// Onwership of cmd is passed to mediahelper class
iMediaHelper->MediaL( iPlaylist->Path(), cmd, &aCallback );
}
else
{
// ownership of cmd is transfered
MediaFromPluginL( &aCallback, cmd );
}
CleanupStack::Pop( cmd );
MPX_DEBUG2("<--CMPXPlaybackEngine::MediaL() aCmd 0x%08x", this);
}
// ----------------------------------------------------------------------------
// Async call: must be added to task queue
// ----------------------------------------------------------------------------
//
EXPORT_C void CMPXPlaybackEngine::SubPlayerNamesL(TUid aPlayerUid,
MMPXPlaybackEngineObserver& aCallback)
{
MPX_FUNC_EX("CMPXPlaybackEngine::SubPlayerNamesL()");
CMPXPlaybackPlugin* p = iPluginHandler->CreatePlayerPluginL(aPlayerUid);
iTaskQueue->AddTaskL(ESubPlayerNames,&aCallback, this, aPlayerUid.iUid, NULL, p);
}
// ----------------------------------------------------------------------------
// Async call: must be added to task queue
// ----------------------------------------------------------------------------
//
void CMPXPlaybackEngine::MediaFromPluginL(
MMPXPlaybackEngineObserver* aCallback,
CMPXCommand* aCmd )
{
MPX_FUNC_EX("CMPXPlaybackEngine::MediaFromPluginL");
CleanupStack::PushL( aCmd );
iTaskQueue->AddTaskL( EMedia, aCallback, this, 0, NULL, NULL, aCmd );
CleanupStack::Pop( aCmd ); // Ownership transferred to the task queue
}
// ----------------------------------------------------------------------------
// Handles a regular heartbeat timer event
// ----------------------------------------------------------------------------
//
void CMPXPlaybackEngine::Beat()
{
// retrieve position from plugins directly
if (iState != EPbStatePlaying)
{
iProgressTimer->Cancel();
}
else
{
TRAP_IGNORE(iTaskQueue->AddTaskL(EProperty, &iReflector,
this, EPbPropertyPosition));
}
}
// ----------------------------------------------------------------------------
// Synchronises the heartbeat timer with system clock
// ----------------------------------------------------------------------------
//
void CMPXPlaybackEngine::Synchronize()
{
MPX_FUNC_EX("CMPXPlaybackEngine::Synchronize");
MPX_DEBUG2("CMPXPlaybackEngine::Synchronize(): iState = %d", iState);
// do the same thing as Beat
Beat();
}
// ----------------------------------------------------------------------------
// Handle accessory event
// ----------------------------------------------------------------------------
//
void CMPXPlaybackEngine::HandleAccesoryEventL(TMPXPlaybackAccessoryMode aMode)
{
MPX_DEBUG2("CMPXPlaybackEngine::HandleAccesoryEventL(%d) entering", aMode);
iClientList->SendMsgL(
TMPXPlaybackMessage( TMPXPlaybackMessage::EAccessoryChanged,
aMode,
0));
#if defined(__HIGH_RESOLUTION_VOLUME)
SetVolumeIncrement( aMode );
#endif // HIGH_RESOLUTION_VOLUME
MPX_DEBUG1("CMPXPlaybackEngine::HandleAccesoryEventL() exiting");
}
// ----------------------------------------------------------------------------
// Callback from plug-in, handle plugin event
// ----------------------------------------------------------------------------
//
void CMPXPlaybackEngine::HandlePluginEvent(
TEvent aEvent,
TInt aData,
TInt aError)
{
TRAP_IGNORE(DoHandlePluginEventL(aEvent, aData, aError));
}
// ----------------------------------------------------------------------------
// Callback from plug-in, handle plugin message
// ----------------------------------------------------------------------------
//
void CMPXPlaybackEngine::HandlePlaybackMessage(
CMPXMessage* aMsg,
TInt aErr)
{
iClientList->SendMsg(aMsg, aErr);
}
// ----------------------------------------------------------------------------
// Handler plugin event
// ----------------------------------------------------------------------------
//
void CMPXPlaybackEngine::DoHandlePluginEventL(
TEvent aEvent,
TInt aData,
TInt aError)
{
MPX_DEBUG5("-->CMPXPlaybackEngine::DoHandlePluginEventL 0x%08x, event %d, data %d, error %d.",
this, aEvent, aData, aError);
TInt disconnectionError = aError;
if ( aEvent == EPPlayerUnavailable )
{
aError = KErrNone;
}
if (aError!=KErrNone)
{
// If error occured during pause event, change to pause but also
// send error code to clients to handle
if ( aEvent == EPPaused )
{
MPX_DEBUG2("CMPXPlaybackEngine::DoHandlePluginEventL(): Pause Error = %d", aError);
if ( aError != KErrNotSupported )
{
// If error during seeking event, keep seeking and set
// plugin state to not intialised
if ( iState == EPbStateSeekingForward ||
iState == EPbStateSeekingBackward )
{
iPluginState = EPbStateNotInitialised;
}
else
{
iState = EPbStatePaused;
iNextState = EPbStatePaused;
SetPlayerActivated(EFalse);
iClientList->SendMsgL(
TMPXPlaybackMessage(
TMPXPlaybackMessage::EStateChanged, iState, aError ));
if ( KErrDied == aError ||
KErrAccessDenied == aError )
{
iPluginState = EPbStateNotInitialised;
// fixed
iAutoResumeHandler->HandlePlaybackComplete(aError);
iAutoResumeHandler->HandlePlaybackStateChange(iState);
}
}
}
else // Pause functionality is not supported, no change of state
// we just send the error back to Ui to let the user know
{
iClientList->SendMsgL(
TMPXPlaybackMessage(TMPXPlaybackMessage::EStateChanged, aEvent, aError));
TMPXPlaybackState s = EPbStatePlaying;
iNextState = EPbStatePlaying;
// Set state first before activation, since activation
// will send a state changed update event as well
SetStateL(s);
}
}
else if ( aEvent != EPSetComplete ) //Not paused and not EPSetComplete
{ // sometimes upnp failed to set value.
MPX_DEBUG4("CMPXPlaybackEngine::DoHandlePluginEventL error aError %d, iState %d, iNextState %d",
aError, iState, iNextState );
SavePlaybackInfoL();
HandlePluginEventErrorHandling(aEvent, aError);
iState = EPbStateStopped;
iClientList->SendMsgL(
TMPXPlaybackMessage(TMPXPlaybackMessage::EStateChanged,iState));
if (aError)
{
iClientList->SendMsgL(
TMPXPlaybackMessage(TMPXPlaybackMessage::EError,aEvent,aError));
}
}
else // SetComplete
{
if ( aError == KErrNotSupported &&
aData == EPbPropertyVolume )
{
iClientList->SendMsgL(
TMPXPlaybackMessage(TMPXPlaybackMessage::EPropertyChanged,
aData, aError));
}
}
}
else // No errors
{
MPX_DEBUG4("CMPXPlaybackEngine::DoHandlePluginEventL, iState %d, iNextState %d, iSkipping %d",
iState, iNextState, iSkipping );
switch(aEvent)
{
case EPInitialised:
case EPClosed:
case EPPaused:
case EPPlaying:
case EPStopped:
case EPDownloadPositionChanged:
case EPDownloadStateChanged:
case EPDownloadCmdPauseDownload:
case EPDownloadCmdResumeDownload:
case EPDownloadCmdCancelDownload:
case EPDownloadStarted:
case EPDownloadingUpdated:
case EPDownloadingComplete:
case EPBufferingStarted:
case EPPlayComplete:
case EPPluginSeeking:
{
UpdateStateMachineL(aEvent, aData, aError);
break;
}
case EPActive:
{
MPX_DEBUG1("CMPXPlaybackEngine::HandlePluginEventL active message.");
SetPlayerActivated(aData);
break;
}
case EPSubPlayersChanged:
{
MPX_DEBUG1("CMPXPlaybackEngine::HandlePluginEventL subplayer changed.");
iClientList->SendMsgL(
TMPXPlaybackMessage(TMPXPlaybackMessage::ESubPlayersChanged));
break;
}
case EPSupportedFeaturesChanged:
{
iClientList->SendMsgL(
TMPXPlaybackMessage(TMPXPlaybackMessage::EPropertyChanged,
EPbPropertySupportedFeatures, aData));
break;
}
case EPSetComplete:
{
if ( aData < iProperties.Count() )
{
iClientList->SendMsgL(
TMPXPlaybackMessage(TMPXPlaybackMessage::EPropertyChanged,
aData, iProperties[aData]));
}
break;
}
case EPDurationChanged:
{
iProperties[EPbPropertyDuration]=aData;
SetPropertiesL();
iClientList->SendMsgL(
TMPXPlaybackMessage(TMPXPlaybackMessage::EPropertyChanged,
EPbPropertyDuration,
iProperties[EPbPropertyDuration]));
break;
}
case EPPlayerUnavailable:
{
if (iInitializer)
{
iInitializer->Close();
}
SavePlaybackInfoL();
iPreservedState = iState;
iPreservedPosition = iProperties[EPbPropertyPosition];
iClientList->SendMsgL(
TMPXPlaybackMessage(TMPXPlaybackMessage::EPlayerUnavailable,
0, disconnectionError));
break;
}
case EPVolumeChanged:
{
iProperties[EPbPropertyVolume] = aData;
if (iInitVolume)
{
iInitVolume = EFalse;
}
else
{
iClientList->SendMsgL(
TMPXPlaybackMessage(TMPXPlaybackMessage::EPropertyChanged,
EPbPropertyVolume,
iProperties[EPbPropertyVolume]));
}
break;
}
case EPMuteChanged:
{
if ( iProperties[EPbPropertyMute] != aData )
{
iProperties[EPbPropertyMute] = aData;
iClientList->SendMsgL(
TMPXPlaybackMessage(TMPXPlaybackMessage::EPropertyChanged,
EPbPropertyMute,
iProperties[EPbPropertyMute]));
}
break;
}
case EPPositionChanged:
{
iProperties[EPbPropertyPosition] = aData;
iClientList->SendMsgL(
TMPXPlaybackMessage(TMPXPlaybackMessage::EPropertyChanged,
EPbPropertyPosition,
iProperties[EPbPropertyPosition]));
break;
}
case EPDownloadFileMoved:
{
CMPXMessage* msg = CMPXMessage::NewL();
CleanupStack::PushL(msg);
TMPXMessageId id=static_cast<TMPXMessageId>(KMPXMessageGeneral);
HBufC* path = reinterpret_cast<HBufC*>(aData);
msg->SetTObjectValueL<TMPXMessageId>(KMPXMessageGeneralId, id);
msg->SetTObjectValueL<TInt>(KMPXMessageGeneralEvent, TMPXPlaybackMessage::EDownloadFileMoved);
msg->SetTObjectValueL<TInt>(KMPXMessageGeneralType, 0);
msg->SetTObjectValueL<TInt>(KMPXMessageGeneralData, 0);
msg->SetTextValueL( KMPXMediaGeneralUri, *path );
iClientList->SendMsg(msg, KErrNone);
CleanupStack::PopAndDestroy( msg );
break;
}
default:
ASSERT(0);
}
}
MPX_DEBUG2("<--CMPXPlaybackEngine::DoHandlePluginEventL() 0x%08x", this);
}
// ----------------------------------------------------------------------------
// Update State Machine
// Handle plugin events that could cause state change in playback-engine
// ----------------------------------------------------------------------------
//
void CMPXPlaybackEngine::UpdateStateMachineL(
TEvent aEvent,
TInt aData,
TInt aError)
{
MPX_DEBUG4("CMPXPlaybackEngine::UpdateStateMachine, iState %d, iNextState %d, iSkipping %d",
iState, iNextState, iSkipping );
TMPXPlaybackState s=iState;
switch(aEvent)
{
case EPInitialised:
{
HandlePluginEventInitialisedL( s, aData );
break;
}
case EPPlaying:
{
s = EPbStatePlaying;
iNextState = EPbStatePlaying;
MPX_DEBUG1("CMPXPlaybackEngine::HandlePluginEventL playing.");
// Set state first before activation, since activation
// will send a state changed update event as well
SetStateL(s);
SetPlayerActivated(ETrue);
iPluginState = EPbStatePlaying;
break;
}
case EPClosed:
{
MPX_DEBUG1("CMPXPlaybackEngine::HandlePluginEventL closed.");
MPX_DEBUG2("CMPXPlaybackEngine::HandlePluginEventL: iState = %d", iState);
iPluginState = EPbStateNotInitialised;
// Do not set state changed event when initialising
if ( iState != EPbStateInitialising && EPbCmdClose == aData)
{
s=EPbStateNotInitialised;
// Set state first before deactivation, since deactivation
// will send a state changed update event as well
SetStateL(s);
SetPlayerActivated(EFalse);
} // else close when stop
break;
}
case EPPaused:
{
if (iState != EPbStateSeekingForward &&
iState != EPbStateSeekingBackward &&
iState != EPbStatePaused &&
!iSkipping)
{
s=EPbStatePaused;
if (EPbStatePlaying == iNextState)
{ // only change state from playing to pause
iNextState = EPbStatePaused;
}
MPX_DEBUG1("CMPXPlaybackEngine::HandlePluginEventL paused.");
// Set state first before deactivation, since deactivation
// will send a state changed update event as well
SetStateL(s);
SetPlayerActivated(EFalse);
}
iPluginState = EPbStatePaused;
break;
}
case EPActive:
{
MPX_DEBUG1("CMPXPlaybackEngine::HandlePluginEventL active message.");
SetPlayerActivated(aData);
break;
}
case EPStopped:
{
MPX_DEBUG1("CMPXPlaybackEngine::HandlePluginEventL stopped.");
s = EPbStateStopped;
SetStateL(s);
TBool handleStop(EFalse);
if (iState != EPbStateSeekingForward &&
iState != EPbStateSeekingBackward &&
!iSkipping &&
iNextState != EPbStatePlaying)
{
handleStop = ETrue;
}
else if (iProgressTimer->IsActive())
{ // stop from remote player
Suspend();
iNextState = EPbStateStopped;
handleStop = ETrue;
} // else stop for seeking
if (handleStop)
{
SetPlayerActivated( EFalse );
s=EPbStateStopped;
if ( iProperties[EPbPropertyPosition] != 0 )
{
iProperties[EPbPropertyPosition]=0;
iClientList->SendMsgL(
TMPXPlaybackMessage(
TMPXPlaybackMessage::EPropertyChanged,
EPbPropertyPosition,
0 ));
}
}
break;
}
case EPPlayComplete:
{
EndSeek();
SavePlaybackCompleteInfoL();
iAutoResumeHandler->HandlePlaybackComplete(aError);
iClientList->SendMsgL(
TMPXPlaybackMessage(TMPXPlaybackMessage::EPropertyChanged,
EPbPropertyPosition,
iProperties[EPbPropertyDuration]));
iTaskQueue->AddTaskL(EHandleNext, NULL, this, 0);
s=EPbStateStopped; //State Changed indication Stopped will be sent
break;
}
case EPDownloadPositionChanged:
{
if ( EPbStateInitialising == s )
{
s=EPbStateBuffering;
}
iClientList->SendMsgL(
TMPXPlaybackMessage( TMPXPlaybackMessage::EDownloadPositionChanged,
0,
aData ));
break;
}
case EPDownloadStateChanged:
{
iClientList->SendMsgL(
TMPXPlaybackMessage( TMPXPlaybackMessage::EDownloadStateChanged,
0,
aData ));
break;
}
case EPDownloadCmdPauseDownload:
{
iClientList->SendMsgL(
TMPXPlaybackMessage( TMPXPlaybackMessage::EDownloadCmdPauseDownload,
0,
aData ));
break;
}
case EPDownloadCmdResumeDownload:
{
iClientList->SendMsgL(
TMPXPlaybackMessage( TMPXPlaybackMessage::EDownloadCmdResumeDownload,
0,
aData ));
break;
}
case EPDownloadCmdCancelDownload:
{
iClientList->SendMsgL(
TMPXPlaybackMessage( TMPXPlaybackMessage::EDownloadCmdCancelDownload,
0,
aData ));
break;
}
case EPDownloadStarted:
{
iClientList->SendMsgL(
TMPXPlaybackMessage( TMPXPlaybackMessage::EDownloadStarted,
0,
aData));
break;
}
case EPDownloadingUpdated:
{
iClientList->SendMsgL(
TMPXPlaybackMessage(TMPXPlaybackMessage::EDownloadUpdated,
0,aData));
s=EPbStateDownloading;
break;
}
// end comment this later
case EPDownloadingComplete:
{
iClientList->SendMsgL(
TMPXPlaybackMessage(TMPXPlaybackMessage::EDownloadComplete,
0,aData));
s=EPbStateStopped;
if ( iProperties[EPbPropertyPosition] != 0 )
{
iProperties[EPbPropertyPosition]=0;
iClientList->SendMsgL(
TMPXPlaybackMessage(
TMPXPlaybackMessage::EPropertyChanged,
EPbPropertyPosition,
0 ));
}
break;
}
case EPBufferingStarted:
{
s = EPbStateBuffering;
iPluginState = EPbStatePlaying; //ToDo: Do we need pluginstate?!?!?
break;
}
case EPPluginSeeking:
{
// suspend playback timer
Suspend();
// Change to plugin seeking state
iNextState = iState;
s = EPbStatePluginSeeking;
MPX_DEBUG1("CMPXPlaybackEngine::HandlePluginEventL EPbStatePluginSeeking.");
// Set state first before activation, since activation
// will send a state changed update event as well
SetStateL(s);
iPluginState = EPbStatePluginSeeking;
break;
}
}
SetStateL(s); //Check if state changed and notify clients.
}
// ----------------------------------------------------------------------------
// Handle Plugin Event : Initialised
// ----------------------------------------------------------------------------
//
void CMPXPlaybackEngine::HandlePluginEventInitialisedL(TMPXPlaybackState& s, TInt aData)
{
#if defined(__HIGH_RESOLUTION_VOLUME)
// Merlin twentysteps hack start
if ( iUri )
{
TParsePtrC parser(*iUri);
MPX_DEBUG2("CMPXPlaybackEngine::DoHandlePluginEventL(): iUri is %S", iUri);
if (parser.Ext().CompareF(KWmaExtension) == 0 || parser.Ext().CompareF(KRaExtension) == 0)
{
// for wma/ra file, increment is always 10 with or without headset
iVolumeIncrement = KMPXLargeVolumeIncrement;
MPX_DEBUG2("CMPXPlaybackEngine::DoHandlePluginEventL it is a wma/ra file, volumeIncrement: %d !!!!", iVolumeIncrement);
}
}
#ifdef __ACCESSORY_FW
else if (iAccessoryObs->AccessoryModeL() == EPbAccessoryWiredHeadset || iAccessoryObs->AccessoryModeL() == EPbAccessoryHeadphones)
#else
else if (iAccessoryObs->AccessoryModeL() == EPbAccessoryHeadset)
#endif // __ACCESSORY_FW
{
// for non wma files with headset, the volume increment is 5
iVolumeIncrement = KMPXSmallVolumeIncrement;
}
#endif // HIGH_RESOLUTION_VOLUME
// twentysteps end
iPluginState = EPbStateStopped;
// Reset corrupted and invalid flags if no error
// Only set if they were not set before, this is because
// calls to SetL() on collection are costly
MPX_DEBUG2("CMPXPlaybackEngine::DoHandlePluginEventL() iDbFlag %x", iDbFlag);
if ( iDbFlag & KMPXMediaGeneralFlagsIsCorrupted ||
iDbFlag & KMPXMediaGeneralFlagsIsInvalid ||
iDbFlag & KMPXMediaGeneralFlagsIsDrmLicenceInvalid )
{
TRAP_IGNORE(
SetFlagBitsL( EFalse,
KMPXMediaGeneralFlagsIsCorrupted |
KMPXMediaGeneralFlagsIsInvalid |
KMPXMediaGeneralFlagsIsDrmLicenceInvalid ));
}
iClientList->SendMsgL(TMPXPlaybackMessage(
TMPXPlaybackMessage::EMediaChanged));
iProperties[EPbPropertyDuration]=aData; //Note, radio has no duration!
SetPropertiesL();
iClientList->SendMsgL(
TMPXPlaybackMessage(TMPXPlaybackMessage::EPropertyChanged,
EPbPropertyDuration,
iProperties[EPbPropertyDuration]));
//Assumption: we take duration==0 to mean "live streaming"
// Check if position is not past the duration
if ( iProperties[EPbPropertyPosition] >= iProperties[EPbPropertyDuration] )
{
iProperties[EPbPropertyPosition] = 0;
}
// Set position to restore saved position.
TRAP_IGNORE( // uPnP leaves if set position in stop state
PluginL()->SetL( EPbPropertyPosition, iProperties[EPbPropertyPosition] ));
iAutoResumeHandler->HandleOpenFileComplete();
// Check if playback should not be started automatically.
if ( iAccessPoint || ( iPlaylist && (!iPlaylist->AutoPlay()) ) )
{
iNextState = EPbStateNotInitialised;
}
TMPXPlaybackState nextState(iNextState); // save next state
switch (iNextState) //What the next state could be (command may have been sent).
{
case EPbStateNotInitialised:
{ // Notify client initialized complete
MPX_DEBUG1("CMPXPlaybackEngine sends msg EInitializeComplete");
iClientList->SendMsgL(
TMPXPlaybackMessage(
TMPXPlaybackMessage::EInitializeComplete,
0,
ETrue));
s = EPbStateInitialised; //This will cause a StateChanged message to be sent
break;
}
case EPbStateStopped:
{ // Play to the end of playlist
PluginL()->CommandL(EPbCmdStop);
if (iInitializer)
{ // close file in the initializer
iInitializer->Close();
}
s = EPbStateStopped;
iClientList->SendMsgL(
TMPXPlaybackMessage(TMPXPlaybackMessage::EPropertyChanged,
EPbPropertyPosition,
iProperties[EPbPropertyPosition]));
break;
}
default:
{
iState = EPbStateStopped;
HandleCommandL(CommandFromState( iNextState ));
s = iState; // change to new state due to handle command
iClientList->SendMsgL(
TMPXPlaybackMessage(TMPXPlaybackMessage::EPropertyChanged,
EPbPropertyPosition,
iProperties[EPbPropertyPosition]));
break;
}
}
if (iInitNext && EPbStateStopped != nextState)
{
//
// Try pre-initialsing the next song, just in case we get there
//
TBool more = iInitializer->Next();
if (!more && iPlaylist->Shuffle())
{ // Reach to the end and shuffle is on, pre-initializer
// needs to re-copy the new shuffle list from engine
if (iInitializer)
{
iInitializer->Close();
}
}
}
}
// ----------------------------------------------------------------------------
// Error handling for Handler plugin event
// ----------------------------------------------------------------------------
//
void CMPXPlaybackEngine::HandlePluginEventErrorHandling(TEvent aEvent, TInt aError)
{
switch (aError)
{
case KErrGeneral:
{
// Track initialization failed
if ( ( aEvent == EPInitialised ) ||
( aEvent == EPPlaying ) )
{
aError = KErrNotSupported;
// Mark item as corrupted
// fall through on purpose
}
else
{
break;
}
}
case KErrArgument:
case KErrNotSupported:
case KErrCorrupt:
case KErrDivideByZero:
{
// Release file handles
TRAP_IGNORE(DoStopL());
// Mark item as corrupted
MarkItemCorrupted( ETrue );
// Reset DRM and invalid flags if they are set
MPX_DEBUG2("CMPXPlaybackEngine::DoHandlePluginEventL() iDbFlag %x", iDbFlag);
if ( iDbFlag & KMPXMediaGeneralFlagsIsInvalid ||
iDbFlag & KMPXMediaGeneralFlagsIsDrmLicenceInvalid )
{
TRAP_IGNORE(
SetFlagBitsL( EFalse,
KMPXMediaGeneralFlagsIsInvalid |
KMPXMediaGeneralFlagsIsDrmLicenceInvalid ));
}
break;
}
case KErrNotFound:
{
// Mark item as invalid
MarkItemInvalid( ETrue );
// Reset DRM and corrupted flags if they are set
MPX_DEBUG2("CMPXPlaybackEngine::DoHandlePluginEventL() iDbFlag %x", iDbFlag);
if ( iDbFlag & KMPXMediaGeneralFlagsIsCorrupted ||
iDbFlag & KMPXMediaGeneralFlagsIsDrmLicenceInvalid )
{
TRAP_IGNORE(
SetFlagBitsL( EFalse,
KMPXMediaGeneralFlagsIsCorrupted |
KMPXMediaGeneralFlagsIsDrmLicenceInvalid ));
}
break;
}
case KErrCANotSupported:
case KErrCANoPermission:
case KErrCANoRights:
case KErrCANoAgent:
case KErrCAOutOfRange:
case KErrCAPendingRights:
case KErrCASizeNotDetermined:
case KErrCANewFileHandleRequired:
{
// Release file handles
TRAP_IGNORE(DoStopL());
// Mark item as DRM Invalid
MarkItemDrmInvalid( ETrue );
// Reset corrupted and invalid flags if they are set
MPX_DEBUG2("CMPXPlaybackEngine::DoHandlePluginEventL() iDbFlag %x", iDbFlag);
if ( iDbFlag & KMPXMediaGeneralFlagsIsCorrupted ||
iDbFlag & KMPXMediaGeneralFlagsIsInvalid )
{
TRAP_IGNORE(
SetFlagBitsL( EFalse,
KMPXMediaGeneralFlagsIsCorrupted |
KMPXMediaGeneralFlagsIsInvalid ));
}
break;
}
case KErrDied:
{
// Release file handles
TRAP_IGNORE(DoStopL());
iNextState = EPbStateNotInitialised;
break;
}
default:
// otherwise send error message to clients
break;
}
}
// ----------------------------------------------------------------------------
// Callback from plug-in. Retrieve the task that resulted in this (which
// removes it from the queue), get the observer and call back with the results.
// Then the player is free to execute the next task, if any
// ----------------------------------------------------------------------------
//
void CMPXPlaybackEngine::HandleProperty(
TMPXPlaybackProperty aProperty,
TInt aValue,
TInt aError)
{
MPX_DEBUG5("-->CMPXPlaybackEngine::HandleProperty 0x%08x prop %d val %d err %d",
this, aProperty, aValue, aError);
if ( iInitVolume && EPbPropertyVolume == aProperty )
{
if (KErrNone == aError)
{
iProperties[EPbPropertyVolume] = aValue;
iInitVolume = EFalse;
}
}
else
{
ASSERT(iTaskQueue->Task() == EProperty && iTaskQueue->Callback() == iCallback);
iCallback->HandleProperty(aProperty,aValue,aError);
iCallback = NULL;
iTaskQueue->CompleteTask();
// notify client the new position during the playback
if ((EPbPropertyPosition == aProperty) && (iProgressTimer->IsActive()))
{
TRAP_IGNORE(iClientList->SendMsgL(
TMPXPlaybackMessage(TMPXPlaybackMessage::EPropertyChanged,
EPbPropertyPosition,aValue)));
}
}
MPX_DEBUG2("<--CMPXPlaybackEngine::HandleProperty 0x%08x", this);
}
// ----------------------------------------------------------------------------
// Callback from plug-in. Retrieve the task that resulted in this (which
// removes it from the queue), get the observer and call back with the results.
// Then the player is free to execute the next task, if any
// ----------------------------------------------------------------------------
//
void CMPXPlaybackEngine::HandleMedia(
CMPXMedia* aMedia,
TInt aError)
{
ASSERT(iTaskQueue->Task() == EMedia && iTaskQueue->Callback() == iCallback);
MPX_FUNC_EX("CMPXPlaybackEngine::HandleMedia()");
iCallback->HandleMedia(aMedia, aError);
iCallback = NULL;
iTaskQueue->CompleteTask();
}
// ----------------------------------------------------------------------------
// Callback from plug-in. Retrieve the task that resulted in this (which
// removes it from the queue), get the observer and call back with the results.
// Then the player is free to execute the next task, if any
// ----------------------------------------------------------------------------
//
void CMPXPlaybackEngine::HandleSubPlayerNames(
TUid /*aPlayer*/,
const MDesCArray* aSubPlayers,
TBool aComplete,
TInt aError)
{
ASSERT(iTaskQueue->Task() == ESubPlayerNames &&
iTaskQueue->Callback() == iCallback);
MPX_DEBUG4("-->CMPXPlaybackEngine::HandleSubPlayerNames 0x%08x, complete %d, err %d",
this, aComplete, aError);
iCallback->HandleSubPlayerNames(TUid::Uid(0), aSubPlayers,
aComplete, aError);
iCallback = NULL;
iTaskQueue->CompleteTask();
MPX_DEBUG2("<--CMPXPlaybackEngine::HandleSubPlayerNames 0x%08x", this);
}
// ----------------------------------------------------------------------------
// Handle media key event
// ----------------------------------------------------------------------------
//
void CMPXPlaybackEngine::HandleCmdBufferEventL(const TMPXPlaybackCmdInfo& aEvent)
{
MPX_DEBUG1("CMPXPlaybackEngine::HandleCmdBufferEventL() entering");
MPX_DEBUG4("CMPXPlaybackEngine::HandleCmdBufferEventL(): offset=%d, state=%d, navKeyBuffered=%d", aEvent.iTrackOffset, iNextState, aEvent.iNavKeyBuffered);
// Fix for EJPI-7BHUGX, if the aEvent.iNavKeyBuffered == 1 and aEvent.iTrackOffset == 0
// That means skip back key press once only, it should not request for media but set pos only
if ( aEvent.iNavKeyBuffered > 1 || aEvent.iTrackOffset != 0 )
{
iNextState = aEvent.iState;
if ( EPlayFromCollection == iPlaySource && iPlaylist )
{
MediaFromCollectionL();
}
else if ( EPlayFromUri == iPlaySource )
{
TRAP_IGNORE( InitL( iUri, &( KNullDesC8 ), NULL, iAccessPoint ) );
}
}
else
{
// If position has changed, set the position in plugin.
// Also the current position should be after the original position
if ( Abs(aEvent.iPos - iProperties[EPbPropertyPosition]) >
KPbPositionChangeThreshold &&
aEvent.iPos < iProperties[EPbPropertyPosition] )
{
MPX_DEBUG1("CMPXPlaybackEngine::HandleCmdBufferEventL(): position changed");
iProperties[EPbPropertyPosition]=aEvent.iPos;
if ( PluginL() )
{
if (iState == EPbStatePlaying)
{
// Need to send pause command to plugin first so that it will
// not keep playing the rest of it's buffer
MPX_DEBUG1("CMPXPlaybackEngine::HandleCmdBufferEventL() send pause command");
PluginL()->CommandL(EPbCmdPause);
}
PluginL()->SetL(EPbPropertyPosition,
iProperties[EPbPropertyPosition]);
}
}
HandleCommandL(CommandFromState( aEvent.iState ));
}
iCmdBuffer->CompleteCommand();
MPX_DEBUG1("CMPXPlaybackEngine::HandleCmdBufferEventL() exiting");
}
// ----------------------------------------------------------------------------
// Handle command skip event from key buffering
// ----------------------------------------------------------------------------
//
void CMPXPlaybackEngine::HandleCmdBufferSkipEventL(
const TMPXPlaybackSkipEvent aSkipEvent )
{
MPX_DEBUG2("==>CMPXPlaybackEngine::HandleCmdBufferSkipEventL(%d) entering", aSkipEvent);
if ( EPbsSkipEventNext == aSkipEvent )
{
iClientList->SendMsgL(
TMPXPlaybackMessage( TMPXPlaybackMessage::ESkipping, 0, 1 ));
TBool wasSkipping( iSkipping );
iSkipping = ETrue;
if ( !wasSkipping )
{
if ( iState == EPbStatePlaying )
{
Suspend();
TRAP_IGNORE(PluginL()->CommandL(EPbCmdPause));
TRAP_IGNORE(SavePlaybackInfoL());
}
else if ( iState == EPbStatePaused )
{
TRAP_IGNORE(SavePlaybackInfoL());
}
}
if ( EPlayFromCollection == iPlaySource && iPlaylist )
{
if ( iPlaylist->Count() > 0 )
{
// Stop if playing or paused
if ( !iPlaylist->Next( ETrue ) )
{
if ( EPbStatePlaying == iNextState ||
EPbStatePaused == iNextState )
{
iCmdBuffer->BufferCommandL(
EPbCmdStop,
iNextState,
iProperties[EPbPropertyPosition]);
}
// End of playlist, send message to clients.
iClientList->SendMsgL(
TMPXPlaybackMessage(TMPXPlaybackMessage::
EReachedEndOfPlaylist));
}
RequestMediaL();
}
}
}
else if ( EPbsSkipEventPrevious == aSkipEvent )
{
TBool wasSkipping( iSkipping );
iSkipping = ETrue;
if ( !wasSkipping && iState == EPbStatePlaying)
{
TRAP_IGNORE(DoStopL());
PluginL()->CommandL( EPbCmdPause );
}
// If first track in list and repeat is off, it will replay current track,
// so do not skip
TBool sendSkip( ETrue );
if ( iPlaylist )
{
if ( 0 != iPlaylist->Index() ||
CMPXCollectionPlaylist::ERepeatOff != iPlaylist->RepeatMode() )
{
sendSkip = ETrue;
}
else
{
sendSkip = EFalse;
}
}
if ( sendSkip && EPlayFromCollection == iPlaySource && iPlaylist )
{
iClientList->SendMsgL(
TMPXPlaybackMessage( TMPXPlaybackMessage::ESkipping, 0, -1 ));
if (iPlaylist->Count()>0)
{
iPlaylist->Previous( ETrue );
RequestMediaL();
}
}
}
else
{
iSkipping = EFalse;
iClientList->SendMsgL(
TMPXPlaybackMessage( TMPXPlaybackMessage::ESkipEnd ));
}
MPX_DEBUG1("<==CMPXPlaybackEngine::HandleCmdBufferSkipEventL()");
}
// ----------------------------------------------------------------------------
// Suspend playback
// ----------------------------------------------------------------------------
//
void CMPXPlaybackEngine::Suspend()
//
// Should stop in current position, i.e. clearing timers etc.
//
{
MPX_FUNC_EX("CMPXPlaybackEngine::Suspend()");
iProgressTimer->Cancel();
EndSeek();
iAutoResumeHandler->CancelResumeTimer();
}
// ----------------------------------------------------------------------------
// Seek timer callback handler
// ----------------------------------------------------------------------------
//
void CMPXPlaybackEngine::SeekTimerTick()
{
TInt& pos=iProperties[EPbPropertyPosition];
pos+=iSeekStep;
if (pos>iProperties[EPbPropertyDuration])
{
pos=iProperties[EPbPropertyDuration];
iSeekTimer->Cancel();
}
if (pos<0)
{
pos=0;
iSeekTimer->Cancel();
}
iSeekStep*=KPbSeekAccelerationFactor;
if (iSeekStep>iMaxSeekStep)
{
iSeekStep=iMaxSeekStep;
}
else if (iSeekStep<-iMaxSeekStep)
{
iSeekStep=-iMaxSeekStep;
}
TRAP_IGNORE(iClientList->SendMsgL(
TMPXPlaybackMessage(TMPXPlaybackMessage::EPropertyChanged,
EPbPropertyPosition,
pos)));
}
// ----------------------------------------------------------------------------
// Seek timer callback
// ----------------------------------------------------------------------------
//
TInt CMPXPlaybackEngine::SeekTimerCallback(TAny* aPtr)
{
static_cast<CMPXPlaybackEngine*>(aPtr)->SeekTimerTick();
return KErrNone;
}
// ----------------------------------------------------------------------------
// Initialise helper method
// ----------------------------------------------------------------------------
//
void CMPXPlaybackEngine::InitL(const TDesC* aSong,
const TDesC8* aType,
RFile* aFile,
TInt aAccessPoint)
{
MPX_DEBUG1("==>CMPXPlaybackEngine::InitL(const TDesC* aSong, const TDesC8* aType, RFile* aFile,TInt aAccessPoint)");
CMPXPlaybackPlugin* p( NULL );
if ( iPluginHandler->Plugin() )
{
TRAP_IGNORE(iPluginHandler->Plugin()->CommandL(EPbCmdClose));
}
if (aSong && aType)
{
MPX_DEBUG2("CMPXPlaybackEngine::InitL(%S)", aSong);
iPluginHandler->SelectPlayerL(*aSong,*aType);
}
else if (aFile)
{
iPluginHandler->SelectPlayerL(*aFile);
}
else
{ // should never happen
ASSERT(0);
}
p=iPluginHandler->Plugin();
CheckPtrL(p);
if (p->Uid()!=iPluginUid)
{ // new plugin or new playlist
iPluginUid = p->Uid();
iInitVolume = ETrue;
p->PropertyL( EPbPropertyVolume );
iClientList->SendMsgL(
TMPXPlaybackMessage(TMPXPlaybackMessage::EPlayerChanged));
}
// Stop and close opened file
TRAP_IGNORE(DoStopL(EFalse));
TRAP_IGNORE(p->CommandL(EPbCmdClose));
// If playing from a playlist, send the index as a data
// parameter. This helps performance as the client
// doesn't need to request the index separately
TInt index( KErrNotFound );
if ( EPlayFromCollection == iPlaySource )
{
index = iPlaylist->Index();
}
TMPXPlaybackMessage msg( TMPXPlaybackMessage::EStateChanged,
EPbStateInitialising,
index );
SetStateL( msg );
iProperties[EPbPropertyPosition]=0;
// make sure our interface is supported
CDesCArray* interfaces = iPluginHandler->SupportedInterfacesL( p->Uid() );
TBool version2InterfaceSupported = EFalse;
if (interfaces->MdcaCount())
{
TInt pos(0);
version2InterfaceSupported = !interfaces->FindIsq(KMPXPlaybackPluginVersion2, pos);
}
delete interfaces;
// cast the plugin to use our interface
if (version2InterfaceSupported)
{
CMPXPlaybackPluginVersion2* plugin = NULL;
plugin = static_cast<CMPXPlaybackPluginVersion2*>(p);
// if cast was successful, then init streaming with access point
if (plugin)
{
if ( iAccessPointSet )
{
if (aSong && aType)
{
plugin->InitStreamingL( *aSong, *aType, aAccessPoint );
}
else if (aFile)
{
plugin->InitStreamingL( *aFile, aAccessPoint );
}
}
else
{
if (aSong && aType)
{
plugin->InitialiseL( *aSong );
}
else if (aFile)
{
plugin->InitialiseL( *aFile );
}
}
}
else // if (plugin)
{
MPX_DEBUG1("CMPXPlaybackEngine::InitL(): *** Init Streaming failed -- failure to convert to expected interface");
}
}
else // if (version2InterfaceSupported)
{
if (aSong && aType)
{
p->InitialiseL( *aSong );
}
else if (aFile)
{
p->InitialiseL( *aFile );
}
}
MPX_DEBUG1("<==CMPXPlaybackEngine::InitL(const TDesC* aSong, const TDesC8* aType, RFile* aFile, TInt aAccessPoint)");
}
// ----------------------------------------------------------------------------
// Command handler
// ----------------------------------------------------------------------------
//
void CMPXPlaybackEngine::HandleCommandL(TMPXPlaybackCommand aCmd, TInt aData )
{
MPX_DEBUG2("CMPXPlaybackEngine::HandleCommandL(%d) entering", aCmd);
switch(aCmd)
{
case EPbCmdPlay:
HandlePlayL();
break;
case EPbCmdStop:
HandleStopL();
break;
case EPbCmdPause:
HandlePauseL();
break;
case EPbCmdNext:
HandleNextL();
break;
case EPbCmdPrevious:
HandlePreviousL();
break;
case EPbCmdPlayWithFadeIn:
HandlePlayWithFadeInL();
break;
case EPbCmdStartSeekForward:
HandleStartSeekL(ETrue);
break;
case EPbCmdStartSeekBackward:
HandleStartSeekL(EFalse);
break;
case EPbCmdStopSeeking:
HandleStopSeekingL();
break;
case EPbCmdIncreaseVolume:
HandleIncreaseVolumeL();
break;
case EPbCmdDecreaseVolume:
HandleDecreaseVolumeL();
break;
case EPbCmdSetVolume:
HandleSetVolumeL( aData );
break;
case EPbCmdMuteVolume:
HandleMuteL(ETrue);
break;
case EPbCmdUnMuteVolume:
HandleMuteL(EFalse);
break;
case EPbCmdClose:
HandleCloseL( aData );
break;
case EPbCmdReplay:
HandleReplayL();
break;
case EPbApplyEffect:
HandleEffectL(aData);
break;
case EPbCmdDisableEffect:
HandleDisableEffectL();
break;
case EPbCmdPreservePosition:
iPreservedPosition = iProperties[EPbPropertyPosition];
break;
case EPbCmdPreserveState:
iPreservedState = iState;
break;
case EPbCmdCloseItem:
HandleCloseItemL( aData );
break;
case EPbCmdCancelInit:
{
if (EPbStateInitialising==iState)
{
PluginL()->CancelRequest();
iNextState = EPbStateStopped;
if (iPluginHandler->Plugin())
{
TRAP_IGNORE(iPluginHandler->Plugin()->CommandL(EPbCmdClose, aData));
}
if (iInitializer)
{
iInitializer->Close();
}
//Needs to update iState and report the change to Ui
SetStateL(EPbStateStopped);
}
break;
}
case EPbCmdResetPreserveState:
{
iPreservedState = EPbStateNotInitialised;
break;
}
case EPbCmdUnloadNonActivePlugin:
{
TUid uid = TUid::Uid(aData);
if (iPluginHandler->Plugin())
{
if (iPluginHandler->Plugin()->Uid() != uid)
{ //not current active plugin
iPluginHandler->UnloadPlugin(uid);
}
}
if (iInitializer)
{
if (iInitializer->PluginUid() == uid)
{ //Plugin loaded in pre-initializer, not active one.
iInitializer->Close();
}
}
break;
}
case EPbCmdClearKeyBuffer:
{
MPX_DEBUG1("CMPXPlaybackEngine::HandleCommandL - EPbCmdClearKeyBuffer");
iCmdBuffer->ClearCommands();
break;
}
case EPbCmdSetAutoResume:
{
iAutoResumeHandler->SetAutoResume( aData );
break;
}
default:
ASSERT(0);
}
MPX_DEBUG1("CMPXPlaybackEngine::HandleCommandL() exiting");
}
// ----------------------------------------------------------------------------
// Handle media properties from collection
// ----------------------------------------------------------------------------
//
void CMPXPlaybackEngine::HandleCollectionMediaL(
const CMPXMedia& aMedia,
TInt aError)
{
MPX_DEBUG3("-->CMPXPlaybackEngine::HandleCollectionMediaL 0x%08x err(%d)",
this, aError);
if (KErrNone == aError)
{
HBufC8* mimeType =
MPXUser::Alloc8L(aMedia.ValueText(KMPXMediaGeneralMimeType));
CleanupStack::PushL(mimeType);
if(iUri)
{
delete iUri;
iUri = NULL;
}
iUri = aMedia.ValueText(KMPXMediaGeneralUri).AllocL();
MPX_DEBUG2("CMPXPlaybackEngine::HandleCollectionMediaL uri %S", iUri);
iItemId = KMPXInvalidItemId;
if (aMedia.IsSupported(KMPXMediaGeneralId))
{
iItemId = aMedia.ValueTObjectL<TMPXItemId>( KMPXMediaGeneralId );
MPX_DEBUG3("CMPXPlaybackEngine::HandleCollectionMediaL iItemId %d %d", iItemId.iId1, iItemId.iId2);
}
iDbFlag = 0;
if ( aMedia.IsSupported( KMPXMediaGeneralFlags ))
{
iDbFlag = aMedia.ValueTObjectL<TUint>( KMPXMediaGeneralFlags );
MPX_DEBUG2("CMPXPlaybackEngine::HandleCollectionMediaL iDbFlag %x", iDbFlag);
}
iMediaDuration = 0;
if ( aMedia.IsSupported( KMPXMediaGeneralDuration ))
{
iMediaDuration = aMedia.ValueTObjectL<TInt>( KMPXMediaGeneralDuration );
MPX_DEBUG2("CMPXPlaybackEngine::HandleCollectionMediaL iMediaDuration %d", iMediaDuration);
}
iAccessPoint = 0;
iAccessPointSet = EFalse;
if ( aMedia.IsSupported(KMPXMediaGeneralExtAccessPoint) )
{
iAccessPoint = aMedia.ValueTObjectL<TInt>( KMPXMediaGeneralExtAccessPoint );
MPX_DEBUG2("CMPXPlaybackEngine::HandleCollectionMediaL iAccessPoint %d", iAccessPoint );
iAccessPointSet = ETrue;
}
if (*iUri == KNullDesC)
{
aError = KErrNotFound;
}
else
{
TRAP( aError, InitL( iUri, mimeType, NULL, iAccessPoint) );
/*
// 20 steps fix
// check whether we are playing WMA files, if so
// the increment has to be KMPXLargeVolumeIncrement
TParsePtrC parser(*iUri);
MPX_DEBUG2("CMPXPlaybackEngine::HandleCollectionMediaL(): iUri is %S", iUri);
if (parser.Ext().CompareF(KWmaExtension) == 0 || parser.Ext().CompareF(KRaExtension) == 0)
{
// for wma file, the increment is always 10 with or without headset
iVolumeIncrement = KMPXLargeVolumeIncrement;
MPX_DEBUG2("CMPXPlaybackEngine::HandleCollectionMediaL it is a wma/ra file, volumeIncrement: %d !!!!", iVolumeIncrement);
}
#if defined(__HIGH_RESOLUTION_VOLUME)
#ifdef __ACCESSORY_FW
else if (iAccessoryObs->AccessoryModeL() == EPbAccessoryWiredHeadset || iAccessoryObs->AccessoryModeL() == EPbAccessoryHeadphones)
#else
else if (iAccessoryObs->AccessoryModeL() == EPbAccessoryHeadset)
#endif // __ACCESSORY_FW
{
// for non wma files with headset, the volume increment is 5
iVolumeIncrement = KMPXSmallVolumeIncrement;
}
#endif // HIGH_RESOLUTION_VOLUME
*/
if ( KErrNone == aError )
{
RestorePlaybackPositionAndStateL( aMedia );
}
else
{
iClientList->SendMsgL(TMPXPlaybackMessage(
TMPXPlaybackMessage::EMediaChanged));
iState = EPbStateStopped;
}
}
CleanupStack::PopAndDestroy(mimeType);
}
else
{
// it'll be incorrect to leave iItemId unchanged, also KMPXInvalidItemId has special handling in
// CreateMediaToSetLC so we'd rather set Id to some actual value even if it had some 'issues'
iItemId = iPlaylist->Path().Id();
}
// Check for error again, just in case above code had any errors
if ( KErrNone != aError )
{
if ( KErrNotFound == aError ||
KErrPathNotFound == aError ||
KErrPermissionDenied == aError )
{
// Mark item as Invalid
MarkItemInvalid( ETrue );
iClientList->SendMsgL(
TMPXPlaybackMessage( TMPXPlaybackMessage::EError,
EPInitialised,
aError ));
}
else
{ // other system error
HandleStopL();
}
}
MPX_DEBUG1("<--CMPXPlaybackEngine::HandleCollectionMediaL()");
}
// ----------------------------------------------------------------------------
// Handle playlist change event
// ----------------------------------------------------------------------------
//
void CMPXPlaybackEngine::HandleCollectionPlaylistChange(TInt aError)
{
MPX_FUNC_EX("CMPXPlaybackEngine::HandleCollectionPlaylistChange");
MPX_DEBUG2("CMPXPlaybackEngine::HandleCollectionPlaylistChange(%d)", aError);
if (KErrNotFound == aError)
{
if ( iPlaylist )
{
TRAP_IGNORE(HandleStopL());
// If playlist is empty now, update state
if ( iPlaylist->Count() == 0 )
{
iNextState = EPbStateNotInitialised;
iState = EPbStateNotInitialised;
}
}
}
else if(KErrEof == aError)
{ // current item removed at the end
TRAP_IGNORE(HandleStopL());
// If playlist is empty now, update state
if ( iPlaylist->Count() == 0 )
{
iNextState = EPbStateNotInitialised;
iState = EPbStateNotInitialised;
}
else
{
TRAP_IGNORE(HandleNextL(1, ETrue));
}
}
else if (iInitializer)
{ // Reset initializer anyway. Make sure it is synced
//iInitializer->Close(); //correct auto playlist crash
}
//update now playing view
TRAP_IGNORE(iClientList->SendMsgL(TMPXPlaybackMessage(
TMPXPlaybackMessage::EPlaylistUpdated)));
}
// ----------------------------------------------------------------------------
// CMPXPlaybackEngine::HandlePluginHandlerEvent
// ----------------------------------------------------------------------------
//
void CMPXPlaybackEngine::HandlePluginHandlerEvent(
TPluginHandlerEvents aEvent,
const TUid& aPluginUid,
TBool aLoaded,
TInt aData)
{
MPX_FUNC_EX("CMPXPlaybackEngine::HandlePluginHandlerEvent");
switch (aEvent)
{
case MMPXPluginHandlerObserver::EPluginAdd:
{
TRAP_IGNORE(SendPluginHandlerMessageL(KMPXMessagePluginAdd, aPluginUid,
EFalse, aData));
break;
}
case MMPXPluginHandlerObserver::EPluginUpdateStart:
{
// Handling the unloading of the previous plugin version and the loading
// of the new plugin version is synchronous and therefore new requests
// will not be processed by the server/engine in between EPluginUpdateStart
// and EPluginUpdateEnd.
//
// If the plugin handler would unload/load plugins asynchronously then a
// mechanism must be created where new requests are not accepted for
// the plugin that is being updated for the duration of the update.
TRAP_IGNORE(SendPluginHandlerMessageL(KMPXMessagePluginUpdateStart,
aPluginUid, aLoaded, aData));
// If the current loaded plugin is being updated
if (iPluginHandler->Plugin() &&
(iPluginHandler->Plugin()->Uid() == aPluginUid))
{
// Complete all outstanding requests
iTaskQueue->CompleteAllTasks(KErrNotReady);
}
break;
}
case MMPXPluginHandlerObserver::EPluginUpdateEnd:
{
TRAP_IGNORE(SendPluginHandlerMessageL(KMPXMessagePluginUpdateEnd,
aPluginUid, aLoaded, aData));
break;
}
case MMPXPluginHandlerObserver::EPluginRemove:
{
// If the current loaded plugin is being removed
if (iPluginHandler->Plugin() &&
(iPluginHandler->Plugin()->Uid() == aPluginUid))
{
// Complete all outstanding requests
iTaskQueue->CompleteAllTasks(KErrNotReady);
}
TRAP_IGNORE(SendPluginHandlerMessageL(KMPXMessagePluginRemove,
aPluginUid, aLoaded));
break;
}
default:
{
// ignore the event
break;
}
}
}
// ----------------------------------------------------------------------------
// CMPXPlaybackEngine::SendPluginHandlerMessageL
// ----------------------------------------------------------------------------
//
void CMPXPlaybackEngine::SendPluginHandlerMessageL(
TInt aMessageId,
const TUid& aPluginUid,
TBool aLoaded,
TInt aVersion /* = 0 */)
{
CMPXMessage* msg = CMPXMedia::NewL();
CleanupStack::PushL(msg);
msg->SetTObjectValueL<TMPXMessageId>(KMPXMessageGeneralId, aMessageId);
msg->SetTObjectValueL<TUid>(KMPXAttrPluginId, aPluginUid);
msg->SetTObjectValueL<TBool>(KMPXAttrPluginLoaded, aLoaded);
if (aVersion > 0)
{
msg->SetTObjectValueL<TInt>(KMPXAttrPluginVersion, aVersion);
}
iClientList->SendMsg(msg, KErrNone);
CleanupStack::PopAndDestroy(msg);
}
// ----------------------------------------------------------------------------
// Handle play command
// ----------------------------------------------------------------------------
//
void CMPXPlaybackEngine::HandlePlayL()
{
MPX_DEBUG1("CMPXPlaybackEngine::HandlePlayL(): entering");
CMPXPlaybackPlugin* p(NULL);
TMPXPlaybackState oldNextState( iNextState );
iNextState = EPbStatePlaying;
if (EPbStateNotInitialised == iPluginState &&
EPlayFromCollection == iPlaySource &&
EPbStatePaused != iState)
{
MediaFromCollectionL();
}
else
{
switch (iState)
{
case EPbStatePlaying: //already playing, send message to update clients
if (EPbStatePaused == iPluginState)
{ // paused due to skipping
PluginL()->CommandL(EPbCmdPlay);
}
iClientList->SendMsgL(
TMPXPlaybackMessage(
TMPXPlaybackMessage::EStateChanged, iState));
break;
case EPbStateNotInitialised: // No song initialised in engine
iNextState = EPbStateNotInitialised;
break;
case EPbStateSeekingForward:
case EPbStateSeekingBackward:
EndSeek();
p = PluginL();
p->CommandL(EPbCmdPlay);
break;
case EPbStatePaused:
case EPbStateStopped:
{
// If playing from collection playlist and currently in
// stopped state, then re-get media attributes
if ( EPlayFromCollection == iPlaySource &&
EPbStateStopped == oldNextState )
{
MediaFromCollectionL();
break;
}
else if ( EPlayFromUri == iPlaySource &&
EPbStateStopped == oldNextState )
{
TRAP_IGNORE( InitL( iUri, &( KNullDesC8 ), NULL, iAccessPoint ) );
break;
}
else
{
// fall through on purpose
}
}
default:
{
p= PluginL();
p->CommandL(EPbCmdPlay);
break;
}
}
}
MPX_DEBUG1("CMPXPlaybackEngine::HandlePlayL(): exiting");
}
// ----------------------------------------------------------------------------
// Handle play command with fade in
// ----------------------------------------------------------------------------
//
void CMPXPlaybackEngine::HandlePlayWithFadeInL()
{
MPX_DEBUG1("CMPXPlaybackEngine::HandlePlayWithFadeInL(): entering");
MPX_DEBUG2("CMPXPlaybackEngine::HandlePlayWithFadeInL(): Ramp = %d", iProperties[EPbPropertyVolumeRamp]);
MPX_DEBUG2("CMPXPlaybackEngine::HandlePlayWithFadeInL(): Position = %d", iProperties[EPbPropertyPosition]);
CMPXPlaybackPlugin* p( PluginL() );
TRAP_IGNORE( // uPnP leaves if set in stop state
p->SetL( EPbPropertyVolumeRamp,
iProperties[EPbPropertyVolumeRamp] ));
p->CommandL(EPbCmdPlay);
iNextState = EPbStatePlaying;
MPX_DEBUG1("CMPXPlaybackEngine::HandlePlayWithFadeInL(): exiting");
}
// ----------------------------------------------------------------------------
// Handle pause command
// ----------------------------------------------------------------------------
//
void CMPXPlaybackEngine::HandlePauseL()
{
MPX_DEBUG1("CMPXPlaybackEngine::HandlePauseL(): entering");
Suspend();
if ( EPbStatePaused == iState )
{
//already paused, send message to update clients
iClientList->SendMsgL(
TMPXPlaybackMessage(
TMPXPlaybackMessage::EStateChanged, iState));
}
else
{
if (EPbStatePlaying == iNextState)
{ // only change state from playing to pause
iNextState = EPbStatePaused;
}
PluginL()->CommandL(EPbCmdPause);
}
MPX_DEBUG1("CMPXPlaybackEngine::HandlePauseL(): exiting");
}
// ----------------------------------------------------------------------------
// Handle stop command
// ----------------------------------------------------------------------------
//
void CMPXPlaybackEngine::HandleStopL()
{
MPX_DEBUG1("CMPXPlaybackEngine::HandleStopL(): entering");
iNextState = EPbStateStopped;
TRAP_IGNORE(DoStopL());
if (iInitializer)
{
iInitializer->Close();
}
MPX_DEBUG1("CMPXPlaybackEngine::HandleStopL(): exiting");
}
// ----------------------------------------------------------------------------
// Stop playback
// ----------------------------------------------------------------------------
//
void CMPXPlaybackEngine::DoStopL(TBool aSavePlaybackInfo)
{
MPX_DEBUG1("==>CMPXPlaybackEngine::DoStopL()");
Suspend();
if (iState == EPbStatePaused || iState == EPbStatePlaying ||
iState == EPbStateInitialising)
{
if (aSavePlaybackInfo && (iState == EPbStatePaused || iState == EPbStatePlaying ))
{
TRAP_IGNORE(SavePlaybackInfoL()); // Leave when MMC eject and database already closed.
}
PluginL()->CommandL(EPbCmdStop); // Leave if router power down
}
MPX_DEBUG1("<==CMPXPlaybackEngine::DoStopL()");
}
// ----------------------------------------------------------------------------
// Handle next track command
// ----------------------------------------------------------------------------
//
void CMPXPlaybackEngine::HandleNextL(
TInt aOffset /*= 1*/,
TBool aIgnoreRepeat /*=EFalse*/ )
{
MPX_ASSERT(aOffset>0);
MPX_DEBUG2("CMPXPlaybackEngine::HandleNextL(%d) entering", aOffset);
EndSeek();
TBool next = ETrue;
TBool notify( ETrue );
if (EPlayFromCollection == iPlaySource && iPlaylist)
{
// Ignore command if playlist empty
if ( iPlaylist->Count() <= 0 )
{
next = EFalse;
notify = EFalse;
}
else
{
while (aOffset-->0)
{
if (!iPlaylist->Next( aIgnoreRepeat ))
{
iClientList->SendMsgL(
TMPXPlaybackMessage(TMPXPlaybackMessage::
EReachedEndOfPlaylist));
iNextState = EPbStateStopped;
if (iPlaylist->IsSingleItemPlaylist())
{
next = EFalse;
}
break;
}
}
}
}
// Check if repeat mode is on and playing from a file or URI
else if ( iProperties[EPbPropertyRepeatMode] != EPbRepeatOff )
{
if ( EPlayFromFile == iPlaySource )
{
TRAP_IGNORE( InitL( NULL, NULL, &iFile, iAccessPoint ));
}
#ifdef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API
else if ( EPlayFromFile64 == iPlaySource )
{
TRAP_IGNORE( Init64L( &iFile64, iAccessPoint ));
}
#endif // SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API
else if ( EPlayFromUri == iPlaySource )
{
TRAP_IGNORE( InitL( iUri, &( KNullDesC8 ), NULL, iAccessPoint ));
}
else
{
HandleStopL();
}
next = EFalse;
}
else
{
HandleStopL();
next = EFalse;
}
if (next)
{
// query collection for next song
MediaFromCollectionL();
}
else if ( notify )
{ // trigger UI to update duration
iClientList->SendMsgL(
TMPXPlaybackMessage(TMPXPlaybackMessage::EStateChanged,iState));
}
MPX_DEBUG1("CMPXPlaybackEngine::HandleNextL() exiting");
}
// ----------------------------------------------------------------------------
// Handle previous command
// ----------------------------------------------------------------------------
//
void CMPXPlaybackEngine::HandlePreviousL(
TInt aOffset /*= -1*/,
TBool aIgnoreRepeat /*=EFalse*/ )
{
MPX_ASSERT(aOffset<0);
MPX_DEBUG2("CMPXPlaybackEngine::HandlePreviousL(%d) entering", aOffset);
EndSeek();
if (EPlayFromCollection == iPlaySource && iPlaylist)
{
// Ignore command if playlist empty
if ( iPlaylist->Count() > 0 )
{
// If first item in list and repeat is off, then replay the song
if ( 0 == iPlaylist->Index() &&
CMPXCollectionPlaylist::ERepeatOff == iPlaylist->RepeatMode() )
{
if ( EPbStatePlaying == iState ||
EPbStatePaused == iState )
{
HandleReplayL();
}
}
else
{
aOffset = -aOffset;
while (aOffset-->0)
{
if (!iPlaylist->Previous( aIgnoreRepeat ))
{
HandleStopL();
break;
}
}
MediaFromCollectionL();
}
}
}
else
{
HandleStopL();
}
MPX_DEBUG1("CMPXPlaybackEngine::HandlePreviousL() exiting");
}
// ----------------------------------------------------------------------------
// Handle replay command
// ----------------------------------------------------------------------------
//
void CMPXPlaybackEngine::HandleReplayL()
{
MPX_DEBUG1("CMPXPlaybackEngine::HandleReplayL(): entering");
EndSeek();
iProperties[EPbPropertyPosition] = 0;
if ( PluginL() )
{
TMPXPlaybackState prevState( iState );
if ( iState == EPbStatePlaying )
{
// Need to send pause command to plugin first so that it will
// not keep playing the rest of it's buffer
MPX_DEBUG1("CMPXPlaybackEngine::HandleReplayL() send pause command");
iState = EPbStatePaused;
PluginL()->CommandL(EPbCmdPause);
}
PluginL()->SetL(EPbPropertyPosition,
iProperties[EPbPropertyPosition]);
if ( prevState == EPbStatePlaying )
{
PluginL()->CommandL(EPbCmdPlay);
}
}
MPX_DEBUG1("CMPXPlaybackEngine::HandleReplayL(): exiting");
}
// ----------------------------------------------------------------------------
// Handle start seeking command
// ----------------------------------------------------------------------------
//
void CMPXPlaybackEngine::HandleStartSeekL(TBool aForward)
{
MPX_DEBUG1("CMPXPlaybackEngine::HandleStartSeekL(): entering");
if (iState==EPbStatePlaying ||
iState==EPbStatePaused ||
iState==EPbStateSeekingForward ||
iState==EPbStateSeekingBackward)
{
Suspend();
if (iState != EPbStateSeekingForward &&
iState != EPbStateSeekingBackward)
{
iNextState = iState;
}
SetStateL(aForward?EPbStateSeekingForward:EPbStateSeekingBackward);
PluginL()->CommandL(EPbCmdPause);
TCallBack cb(SeekTimerCallback,this);
iSeekStep = aForward ? KPbInitialSeekStepMilliSeconds :
-KPbInitialSeekStepMilliSeconds;
if ( iSeekTimer->IsActive() )
iSeekTimer->Cancel();
iSeekTimer->Start(KPbSeekIntervalMicroSeconds,
KPbSeekIntervalMicroSeconds, cb);
MPX_DEBUG2("CMPXPlaybackEngine sends msg EStateChanged to %d", iState);
iClientList->SendMsgL(
TMPXPlaybackMessage(TMPXPlaybackMessage::EStateChanged,iState));
}
MPX_DEBUG1("CMPXPlaybackEngine::HandleStartSeekL(): exiting");
}
// ----------------------------------------------------------------------------
// Handle stop seeking command
// ----------------------------------------------------------------------------
//
void CMPXPlaybackEngine::HandleStopSeekingL()
{
MPX_DEBUG1("CMPXPlaybackEngine::HandleStopSeekingL(): entering");
// Only perform actions if we are currently in seeking state
if (iState == EPbStateSeekingForward ||
iState == EPbStateSeekingBackward)
{
EndSeek();
if (EPbStateNotInitialised == iPluginState &&
EPlayFromCollection == iPlaySource )
{
iPreservedPosition = iProperties[EPbPropertyPosition];
MediaFromCollectionL();
}
else
{
PluginL()->SetL(EPbPropertyPosition,iProperties[EPbPropertyPosition]);
iState = iNextState;
switch ( iState )
{
case EPbStatePlaying:
{
iClientList->SendMsgL( // update UI icons
TMPXPlaybackMessage(TMPXPlaybackMessage::EStateChanged,iState));
PluginL()->CommandL( EPbCmdPlay );
break;
}
case EPbStatePaused:
{
iClientList->SendMsgL( // update UI icons
TMPXPlaybackMessage(TMPXPlaybackMessage::EStateChanged,iState));
break;
}
default:
break;
}
}
}
MPX_DEBUG1("CMPXPlaybackEngine::HandleStopSeekingL(): exiting");
}
// ----------------------------------------------------------------------------
// Handle increase volume command
// ----------------------------------------------------------------------------
//
void CMPXPlaybackEngine::HandleIncreaseVolumeL()
{
TInt level( iProperties[EPbPropertyVolume] );
#if defined(__HIGH_RESOLUTION_VOLUME)
// if we already rounded up last time, don't have to increase,
// reset flag
if (!iVolRoundedUp)
{
level += iVolumeIncrement;
}
#else
level += iVolumeIncrement;
#endif
// Ensure that level is within min and max values
if (level > KPbPlaybackVolumeLevelMax)
{
level = KPbPlaybackVolumeLevelMax;
}
if (level < KPbPlaybackVolumeLevelMin)
{
level = KPbPlaybackVolumeLevelMin;
}
SetL(EPbPropertyVolume, level);
}
// ----------------------------------------------------------------------------
// Handle decrease volume command
// ----------------------------------------------------------------------------
//
void CMPXPlaybackEngine::HandleDecreaseVolumeL()
{
TInt level( iProperties[EPbPropertyVolume] - iVolumeIncrement );
// Ensure that level is within min and max values
if (level > KPbPlaybackVolumeLevelMax)
{
level = KPbPlaybackVolumeLevelMax;
}
if (level < KPbPlaybackVolumeLevelMin)
{
level = KPbPlaybackVolumeLevelMin;
}
SetL(EPbPropertyVolume, level);
}
// ----------------------------------------------------------------------------
// Handle set volume command
// ----------------------------------------------------------------------------
//
void CMPXPlaybackEngine::HandleSetVolumeL(TInt aVolume)
{
TInt level = aVolume;
// Ensure that level is within min and max values
if (level > KPbPlaybackVolumeLevelMax)
{
level = KPbPlaybackVolumeLevelMax;
}
if (level < KPbPlaybackVolumeLevelMin)
{
level = KPbPlaybackVolumeLevelMin;
}
SetL(EPbPropertyVolume, level);
}
// ----------------------------------------------------------------------------
// Handle mute command
// ----------------------------------------------------------------------------
//
void CMPXPlaybackEngine::HandleMuteL(TBool aMute)
{
SetL(EPbPropertyMute, aMute);
}
// ----------------------------------------------------------------------------
// Handle close command
// ----------------------------------------------------------------------------
//
void CMPXPlaybackEngine::HandleCloseL( TInt aData )
{
MPX_DEBUG1("CMPXPlaybackEngine::HandleCloseL(): entering");
if (iPluginHandler->Plugin())
{
TRAP_IGNORE(DoStopL());
iNextState = EPbStateNotInitialised;
TRAP_IGNORE(iPluginHandler->Plugin()->CommandL(EPbCmdClose, aData));
DoClose();
}
if (iInitializer)
{
iInitializer->Close();
}
MPX_DEBUG1("CMPXPlaybackEngine::HandleCloseL(): exiting");
}
// ----------------------------------------------------------------------------
// Handle a custom command
// ----------------------------------------------------------------------------
//
void CMPXPlaybackEngine::HandleEffectL(TInt aData)
{
MPX_FUNC_EX("CMPXPlaybackEngine::HandleEffectL()");
if(iPluginHandler->Plugin())
{
iPluginHandler->Plugin()->CommandL(EPbApplyEffect, aData);
}
}
// ----------------------------------------------------------------------------
// Handle a custom command
// ----------------------------------------------------------------------------
//
void CMPXPlaybackEngine::HandleDisableEffectL()
{
MPX_FUNC_EX("CMPXPlaybackEngine::HandleDisableEffectL()");
if(iPluginHandler->Plugin())
{
iPluginHandler->Plugin()->CommandL(EPbCmdDisableEffect);
}
}
// ----------------------------------------------------------------------------
// Handle request to close a specific item
// ----------------------------------------------------------------------------
//
void CMPXPlaybackEngine::HandleCloseItemL( TInt aItemId )
{
MPX_FUNC_EX("CMPXPlaybackEngine::HandleCloseItemL()");
if( iPlaylist )
{
// If the item is currently in play, close playback or
// if item is currently in the initializer
if( iPlaylist->Path().Id().ApproxEqual( aItemId ) )
{
HandleStopL();
}
else if(iInitializer)
{
TInt nextIndex;
TBool repeatMode;
repeatMode = iPlaylist->RepeatMode();
TBool nextFound = iPlaylist->NextIndex( repeatMode, nextIndex );
TMPXItemId nextItemId = iPlaylist->Path().IdOfIndex( nextIndex );
if((iInitializer->CurrentInitItemId().iId2 == aItemId) ||
( iInitNext && nextFound && nextItemId.ApproxEqual( aItemId )))
{
iInitializer->Close();
}
}
}
}
// ----------------------------------------------------------------------------
// Sets the plug-in properties
// ----------------------------------------------------------------------------
//
void CMPXPlaybackEngine::SetPropertiesL()
{
MPX_FUNC_EX("CMPXPlaybackEngine::SetPropertiesL()");
iMaxSeekStep = iProperties[EPbPropertyDuration]/KPercentMultiplier*KPbMaxSeekStepPercent;
MPX_DEBUG2("CMPXPlaybackEngine::SetPropertiesL(): iMediaDuration = %d", iMediaDuration);
MPX_DEBUG2("CMPXPlaybackEngine::SetPropertiesL(): iProperties[EPbPropertyDuration] = %d", iProperties[EPbPropertyDuration]);
if ( Abs(iMediaDuration - iProperties[EPbPropertyDuration]) >
KPbDurationChangeThreshold )
{
MPX_DEBUG1("CMPXPlaybackEngine::SetPropertiesL(): Duration not equal");
// Set duration if it's different than what collection has
if ( iPlaylist)
{
if ( iPlaylist->Count() && !iPlaylist->EmbeddedPlaylist() )
{
MPX_DEBUG1("CMPXPlaybackEngine::SetPropertiesL(): Setting duration");
CMPXMedia* media( CreateMediaToSetLC( iPlaylist->Path() ));
iMediaDuration = iProperties[EPbPropertyDuration];
media->SetTObjectValueL( KMPXMediaGeneralDuration,
iProperties[EPbPropertyDuration] );
iPlaylist->SetL( *media );
CleanupStack::PopAndDestroy( media );
}
}
}
}
// ----------------------------------------------------------------------------
// Stop seeking timer
// ----------------------------------------------------------------------------
//
void CMPXPlaybackEngine::EndSeek()
{
if (iSeekTimer)
{
iSeekTimer->Cancel();
}
}
// ----------------------------------------------------------------------------
// Set playback state
// ----------------------------------------------------------------------------
//
void CMPXPlaybackEngine::SetStateL(TMPXPlaybackState aState)
{
MPX_DEBUG2("CMPXPlaybackEngine::SetStateL(%d): entering", aState);
TMPXPlaybackMessage msg( TMPXPlaybackMessage::EStateChanged,
aState );
SetStateL( msg );
MPX_DEBUG1("CMPXPlaybackEngine::SetStateL(): exiting");
}
// ----------------------------------------------------------------------------
// Set playback state
// ----------------------------------------------------------------------------
//
void CMPXPlaybackEngine::SetStateL( TMPXPlaybackMessage& aMsg )
{
MPX_DEBUG1("CMPXPlaybackEngine::SetStateL(aMsg): entering");
TMPXPlaybackState state( static_cast<TMPXPlaybackState>( aMsg.Type() ));
MPX_DEBUG2("CMPXPlaybackEngine::SetStateL(): state = %d", state);
if ( state!=iState )
{
iState = state;
iAutoResumeHandler->HandlePlaybackStateChange( iState );
MPX_DEBUG2("CMPXPlaybackEngine sends msg EStateChanged to %d", iState);
iClientList->SendMsgL( aMsg );
}
// Restart progress timer
if (EPbStatePlaying == iState && !iProgressTimer->IsActive())
{
iProgressTimer->Start(ETwelveOClock,this);
}
MPX_DEBUG1("CMPXPlaybackEngine::SetStateL(aMsg): exiting");
}
// ----------------------------------------------------------------------------
// Set player activated
// ----------------------------------------------------------------------------
//
void CMPXPlaybackEngine::SetPlayerActivated(TBool aActive)
{
MPX_DEBUG3("CMPXPlaybackEngine::SetPlayerActivated old = %d, new = %d",
iPlayerActive, aActive);
if (iPlayerActive != aActive)
{
iPlayerActive = aActive;
// triggle clients to update playback state
TRAP_IGNORE(iClientList->SendMsgL(
TMPXPlaybackMessage(TMPXPlaybackMessage::EStateChanged, iState)));
MPX_DEBUG1("Playback Engine notify server active player chnaged.");
TRAP_IGNORE(iObserver.HandleActiveEngineL(this, iPlayerActive));
}
MPX_DEBUG1("CMPXPlaybackEngine::SetPlayerActivated(): exiting");
}
// ----------------------------------------------------------------------------
// Execute a async task
// ----------------------------------------------------------------------------
//
void CMPXPlaybackEngine::ExecuteTask(
TInt aTask,
TInt aParamData,
TAny* aPtrData,
const CBufBase& aBuf,
TAny* aCallback,
CBase* aCObject1,
CBase* aCObject2)
{
TRAPD(err, ExecuteTaskL(aTask, aParamData, aPtrData,
aCallback, aBuf, aCObject1, aCObject2));
if (KErrNone != err)
{
HandleError(aTask, err, aParamData);
}
}
// ----------------------------------------------------------------------------
// Indicates that a task was terminated with an error.
// This will be called in case of a plugin update/removal.
// ----------------------------------------------------------------------------
//
void CMPXPlaybackEngine::HandleTaskError(
TInt aTask,
TAny* /*aPtrData*/,
TAny* /*aCallback*/,
TInt aError)
{
MPX_FUNC("CMPXCollectionClientContext::HandleTaskError");
HandleError(aTask, aError);
}
// ----------------------------------------------------------------------------
// Execute a async task
// ----------------------------------------------------------------------------
//
void CMPXPlaybackEngine::ExecuteTaskL(
TInt aTask,
TInt aParamData,
TAny* aPtrData,
TAny* aCallback,
const CBufBase& /*aBuf*/,
CBase* aCObject1,
CBase* /*aCObject2*/)
{
MPX_DEBUG5("-->CMPXPlaybackEngine::ExecuteTaskL 0x%08x cb 0x%08x (%d, %d)",
this, aCallback, aTask, aParamData);
if ( aTask != EHandleNext )
{
ASSERT(aCallback);
iCallback = static_cast<MMPXPlaybackEngineObserver*>(aCallback);
}
CMPXPlaybackPlugin* p = aPtrData ?
static_cast<CMPXPlaybackPlugin*>(aPtrData) :
iPluginHandler->Plugin();
switch(aTask)
{
case EProperty:
{
CheckPtrL(p);
p->PropertyL(static_cast<TMPXPlaybackProperty>(aParamData));
break;
}
case EMedia:
{
iMediaAttrs.Reset();
CMPXCommand* cmd( static_cast<CMPXAttributeSpecs*>(aCObject1));
const TDesC& attr = cmd->ValueText( KMPXCommandMediaAttribute );
TPtrC8 ptr = MPXUser::Ptr( attr );
RDesReadStream readStream( ptr );
CleanupClosePushL( readStream );
// Internalize attributes
::InternalizeL( iMediaAttrs, readStream );
CleanupStack::PopAndDestroy( &readStream );
CheckPtrL( p );
TMPXPlaybackState state(State());
if (( EPbStateInitialising == state ||
EPbStatePlaying == state ||
EPbStatePaused == state ||
EPbStateStopped == state ||
EPbStateBuffering == state ||
EPbStateDownloading == state ||
EPbStateInitialised == state ))
{
CMPXAttributeSpecs* specs( NULL );
if ( cmd->IsSupported( KMPXCommandMediaAttributeSpecs ) )
{
specs = cmd->Value<CMPXAttributeSpecs>( KMPXCommandMediaAttributeSpecs );
User::LeaveIfNull(specs);
}
p->MediaL( iMediaAttrs.Array(), specs );
}
else
{
CMPXMedia *media = CMPXMedia::NewL();
CleanupStack::PushL(media);
media->SetTObjectValueL(KMPXMediaColDetailMediaNotAvailable,
ETrue);
HandleMedia(media, KErrNone);
CleanupStack::PopAndDestroy(media);
}
}
break;
case ESubPlayerNames:
{
CheckPtrL(p);
p->SubPlayerNamesL();
break;
}
case EHandleNext:
{
HandleNextL();
if( iPlaylist )
{
iClientList->SendMsgL(TMPXPlaybackMessage(
TMPXPlaybackMessage::EMediaChanged));
}
SetStateL( iState );
iTaskQueue->CompleteTask();
break;
}
default:
ASSERT(0);
}
MPX_DEBUG4("<--CMPXPlaybackEngine::ExecuteTaskL 0x%08x (%d, %d): Exiting",
this, aTask, aParamData);
}
// ----------------------------------------------------------------------------
// Error happens upon request
// ----------------------------------------------------------------------------
//
void CMPXPlaybackEngine::HandleError(
TInt aTask,
TInt aError,
TInt aParamData /* = 0 */)
{
MPX_DEBUG3("-->CMPXPlaybackEngine::HandleError() 0x%08x: aError %d", this, aError);
switch (aTask)
{
case EProperty:
iCallback->HandleProperty(
static_cast<TMPXPlaybackProperty>(aParamData),
0,aError);
iCallback = NULL;
break;
case EMedia:
{
iCallback->HandleMedia(NULL, aError);
iCallback = NULL;
}
break;
case ESubPlayerNames:
{
TUid piid=TUid::Uid(aParamData);
iCallback->HandleSubPlayerNames(piid, NULL, ETrue, aError);
iCallback = NULL;
}
break;
default:
ASSERT(0);
break;
}
iTaskQueue->CompleteTask();
MPX_DEBUG3("<--CMPXPlaybackEngine::HandleError() 0x%08x: aError %d", this, aError);
}
// ----------------------------------------------------------------------------
// Get command from state
// ----------------------------------------------------------------------------
//
TMPXPlaybackCommand CMPXPlaybackEngine::CommandFromState(
TMPXPlaybackState aState )
{
MPX_DEBUG2("CMPXPlaybackEngine::CommandFromState(): aState %d", aState);
TMPXPlaybackCommand cmd(EPbCmdStop);
switch ( aState )
{
case EPbStatePlaying:
cmd = EPbCmdPlay;
break;
case EPbStatePaused:
cmd = EPbCmdPause;
break;
case EPbStateStopped:
cmd = EPbCmdStop;
break;
default:
break;
}
return cmd;
}
// ----------------------------------------------------------------------------
// Do close
// ----------------------------------------------------------------------------
//
void CMPXPlaybackEngine::DoClose()
{
MPX_FUNC_EX("CMPXPlaybackEngine::DoClose()");
if (iTaskQueue)
{
iTaskQueue->CancelRequests();
}
iAutoResumeHandler->CancelResumeTimer();
if (iProgressTimer)
{
iProgressTimer->Cancel();
}
if (iSeekTimer)
{
iSeekTimer->Cancel();
}
iCmdBuffer->ClearCommands();
iFile.Close();
#ifdef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API
iFile64.Close();
#endif // SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API
delete iPlaylist;
iPlaylist = NULL;
delete iUri;
iUri = NULL;
iItemId = KMPXInvalidItemId;
iPlaySource = EPlayNone;
iState = EPbStateNotInitialised;
iNextState = EPbStateNotInitialised;
}
// ----------------------------------------------------------------------------
// URI from collection
// ----------------------------------------------------------------------------
//
void CMPXPlaybackEngine::MediaFromCollectionL()
{
MPX_FUNC_EX("CMPXPlaybackEngine::MediaFromCollectionL");
if (iInitNext)
{
iInitializer->Init(*iPlaylist);
iInitializer->SetActiveL();
}
else
{
RArray<TMPXAttribute> attrs;
CleanupClosePushL(attrs);
attrs.AppendL(KMPXMediaGeneralId);
attrs.AppendL(KMPXMediaGeneralUri);
attrs.AppendL(KMPXMediaGeneralMimeType);
attrs.AppendL(KMPXMediaGeneralLastPlaybackPosition);
attrs.AppendL(KMPXMediaGeneralFlags);
if (iPlaylist) ///in some cases this could be empty
{
iPlaylist->MediaL(attrs.Array(),*this);
}
CleanupStack::PopAndDestroy(&attrs);
}
}
// ----------------------------------------------------------------------------
// Save playback position
// ----------------------------------------------------------------------------
//
void CMPXPlaybackEngine::SavePlaybackInfoL()
{
MPX_DEBUG1("CMPXPlaybackEngine::SavePlaybackInfoL() entering");
if ( iPlaylist)
{
if (iPlaylist->Count() && !iPlaylist->EmbeddedPlaylist())
{
CMPXMedia* media( CreateMediaToSetLC( iPlaylist->Path() ));
// Save position, if at the end, then save position is 0
// Due to timer callbacks, the current position may not be exactly
// at the same value as the duration, thus must give it a
// threshold to be within.
TInt savePosition( iProperties[EPbPropertyPosition] );
if ( Abs( iProperties[EPbPropertyDuration] - savePosition ) <
KPbPositionChangeThreshold )
{
savePosition = 0;
}
media->SetTObjectValueL( KMPXMediaGeneralLastPlaybackPosition,
savePosition );
iPlaylist->SetL( *media );
CleanupStack::PopAndDestroy(media);
}
}
MPX_DEBUG1("CMPXPlaybackEngine::SavePlaybackInfoL() exiting");
}
// ----------------------------------------------------------------------------
// Increments play count
// ----------------------------------------------------------------------------
//
void CMPXPlaybackEngine::SavePlaybackCompleteInfoL()
{
MPX_DEBUG1("CMPXPlaybackEngine::SavePlaybackCompleteInfoL() entering");
if ( iPlaylist )
{
if ( iPlaylist->Count() && !iPlaylist->EmbeddedPlaylist() )
{
CMPXMedia* media( CreateMediaToSetLC( iPlaylist->Path() ));
// Increment play count
// Collection implementation will increment count by the
// value provided
media->SetTObjectValueL( KMPXMediaGeneralPlayCount,
1 );
// reset the last playback position to 0
media->SetTObjectValueL( KMPXMediaGeneralLastPlaybackPosition,
0 );
// Set last play time
TTime now;
now.UniversalTime();
media->SetTObjectValueL(KMPXMediaGeneralLastPlaybackTime,
now.Int64() );
iPlaylist->SetL( *media );
CleanupStack::PopAndDestroy( media );
}
}
MPX_DEBUG1("CMPXPlaybackEngine::SavePlaybackCompleteInfoL() exiting");
}
// ----------------------------------------------------------------------------
// Restore playback position if it was saved previously
// ----------------------------------------------------------------------------
//
void CMPXPlaybackEngine::RestorePlaybackPositionAndStateL(
const CMPXMedia& aMedia )
{
MPX_DEBUG1("CMPXPlaybackEngine::RestorePlaybackPositionAndStateL() entering");
// Restore Position
iProperties[EPbPropertyPosition] = 0;
if ( KErrNotFound != iPreservedPosition )
{
iProperties[EPbPropertyPosition] = iPreservedPosition;
iPreservedPosition = KErrNotFound;
}
else
{
// Check media
if (aMedia.IsSupported(KMPXMediaGeneralLastPlaybackPosition))
{
iProperties[EPbPropertyPosition] =
aMedia.ValueTObjectL<TInt>( KMPXMediaGeneralLastPlaybackPosition );
}
}
// Restore State
if ( EPbStateNotInitialised != iPreservedState )
{
iNextState = iPreservedState;
iPreservedState = EPbStateNotInitialised;
}
MPX_DEBUG1("CMPXPlaybackEngine::RestorePlaybackPositionAndStateL() exiting");
}
// ----------------------------------------------------------------------------
// Sets the volume increment depending on accessory state
// ----------------------------------------------------------------------------
//
void CMPXPlaybackEngine::SetVolumeIncrement( TMPXPlaybackAccessoryMode aMode )
{
MPX_DEBUG2("CMPXPlaybackEngine::SetVolumeIncrement(%d) entering", aMode);
switch ( aMode )
{
#ifdef __ACCESSORY_FW
case EPbAccessoryWiredHeadset:
case EPbAccessoryHeadphones:
#else
case EPbAccessoryHeadset:
#endif // __ACCESSORY_FW
{
// twentysteps start
// check whether we are playing WMA files, if so the increment has to be KMPXLargeVolumeIncrement
if(iUri)
{
//MPX_DEBUG1("still alive one !!!!");
TParsePtrC parser(*iUri);
MPX_DEBUG2("CMPXPlaybackEngine::SetVolumeIncrement(): iUri is %S", iUri);
if (parser.Ext().CompareF(KWmaExtension) == 0 || parser.Ext().CompareF(KRaExtension) == 0 )
{
iVolumeIncrement = KMPXLargeVolumeIncrement;
}
else
{
iVolumeIncrement = KMPXSmallVolumeIncrement;
}
}
else
{
MPX_DEBUG1("CMPXPlaybackEngine::SetVolumeIncrement iUri is NULL");
iVolumeIncrement = KMPXSmallVolumeIncrement;
}
MPX_DEBUG2("CMPXPlaybackEngine::SetVolumeIncrement(): Headset is inserted, increment is %d", iVolumeIncrement);
// twentysteps end
// uncomment this when twentysteps is removed iVolumeIncrement = KMPXSmallVolumeIncrement;
break;
}
default:
{
// for everything else check what is the current volume value
// and if an not an interval of KMPXLargeVolumeIncrement,
// which could be the case if the last
// time user listened to music and wired headset was plugged in,
// then convert the value used to an increment of KMPXLargeVolumeIncrement.
MPX_DEBUG2("CMPXPlaybackEngine::SetVolumeIncrement(): NOT a headset, increment is %d", KMPXLargeVolumeIncrement);
iVolumeIncrement = KMPXLargeVolumeIncrement;
if ( iProperties[EPbPropertyVolume] > KPbPlaybackVolumeLevelMin &&
iProperties[EPbPropertyVolume] < KPbPlaybackVolumeLevelMax)
{
#if defined(__HIGH_RESOLUTION_VOLUME)
// if we will round up the volume to next increment of 10, set the flag
// so when the headset is unplugged, we just increment it again.
if (iProperties[EPbPropertyVolume] % KMPXLargeVolumeIncrement)
{
iVolRoundedUp = ETrue;
}
#endif
while ( iProperties[EPbPropertyVolume] % KMPXLargeVolumeIncrement &&
iProperties[EPbPropertyVolume] <= KPbPlaybackVolumeLevelMax )
{
// increase volume until it's a valid increment of KMPXLargeVolumeIncrement
iProperties[EPbPropertyVolume]++;
}
}
break;
}
}
MPX_DEBUG1("CMPXPlaybackEngine::SetVolumeIncrement() exiting");
}
// ----------------------------------------------------------------------------
// Marks the current item as corrupted
// ----------------------------------------------------------------------------
//
void CMPXPlaybackEngine::MarkItemCorrupted( const TBool aCorrupted )
{
MPX_DEBUG2("CMPXPlaybackEngine::MarkItemCorrupted(%d) entering", aCorrupted);
TRAP_IGNORE( SetFlagBitsL( aCorrupted, KMPXMediaGeneralFlagsIsCorrupted ));
MPX_DEBUG1("CMPXPlaybackEngine::MarkItemCorrupted() exiting");
}
// ----------------------------------------------------------------------------
// Marks the current item as invalid
// ----------------------------------------------------------------------------
//
void CMPXPlaybackEngine::MarkItemInvalid( const TBool aInvalid )
{
MPX_DEBUG2("CMPXPlaybackEngine::MarkItemInvalid(%d) entering", aInvalid);
TRAP_IGNORE( SetFlagBitsL( aInvalid, KMPXMediaGeneralFlagsIsInvalid ));
MPX_DEBUG1("CMPXPlaybackEngine::MarkItemInvalid() exiting");
}
// ----------------------------------------------------------------------------
// Marks the current item as DRM invalid
// ----------------------------------------------------------------------------
//
void CMPXPlaybackEngine::MarkItemDrmInvalid( const TBool aDrmInvalid )
{
MPX_DEBUG2("CMPXPlaybackEngine::MarkItemDrmInvalid(%d) entering", aDrmInvalid);
TRAP_IGNORE( SetFlagBitsL( aDrmInvalid, KMPXMediaGeneralFlagsIsDrmLicenceInvalid ));
MPX_DEBUG1("CMPXPlaybackEngine::MarkItemDrmInvalid() exiting");
}
// ----------------------------------------------------------------------------
// Sets flag bits
// ----------------------------------------------------------------------------
//
void CMPXPlaybackEngine::SetFlagBitsL(
const TBool aSet,
const TUint aFlag )
{
MPX_DEBUG3("CMPXPlaybackEngine::SetFlagBitsL(%d, %d) entering", aSet, aFlag);
if ( iPlaylist)
{
if (iPlaylist->Count() && !iPlaylist->EmbeddedPlaylist())
{
CMPXMedia* media( CreateMediaToSetLC( iPlaylist->Path() ));
// Set flag
TUint flag( 0 );
if ( aSet )
{
flag = KMPXMediaGeneralFlagsSetOrUnsetBit;
}
flag |= aFlag;
media->SetTObjectValueL( KMPXMediaGeneralFlags,
flag );
iPlaylist->SetL( *media );
CleanupStack::PopAndDestroy( media );
}
}
MPX_DEBUG1("CMPXPlaybackEngine::SetFlagBitsL() exiting");
}
// ----------------------------------------------------------------------------
// Creates a CMPXMedia object to be used to Set attributes
// ----------------------------------------------------------------------------
//
CMPXMedia* CMPXPlaybackEngine::CreateMediaToSetLC( const CMPXCollectionPath& aPath )
{
MPX_DEBUG1("-->CMPXPlaybackEngine::CreateMediaToSetLC()");
// Create new Media object to set
CMPXMedia* media = CMPXMedia::NewL();
CleanupStack::PushL(media);
media->SetTObjectValueL( KMPXMediaGeneralType,
EMPXItem );
media->SetTObjectValueL( KMPXMediaGeneralCategory,
EMPXSong );
media->SetTObjectValueL( KMPXMediaGeneralCollectionId,
aPath.Id( CMPXCollectionPath::ECollectionUid ));
if (iItemId != KMPXInvalidItemId)
{
media->SetTObjectValueL<TMPXItemId>(KMPXMediaGeneralId, iItemId);
}
else if (iUri)
{
media->SetTextValueL( KMPXMediaGeneralUri, *iUri);
}
else
{
media->SetTObjectValueL<TMPXItemId>( KMPXMediaGeneralId , aPath.Id() );
}
MPX_DEBUG1("<--CMPXPlaybackEngine::CreateMediaToSetLC()");
return media;
}
// ----------------------------------------------------------------------------
// Sends a request to iMediaHelper to request media
// ----------------------------------------------------------------------------
//
void CMPXPlaybackEngine::RequestMediaL()
{
MPX_FUNC( "CMPXPlaybackEngine::RequestMediaL" );
CMPXCommand* cmd = CMPXCommand::NewL();
CleanupStack::PushL( cmd );
cmd->SetTObjectValueL<TInt>(KMPXCommandGeneralId, KMPXCommandContentIdMedia);
CBufBase* buf = CBufFlat::NewL( KMPXBufGranularity );
CleanupStack::PushL( buf );
// Setup array buffer
RArray<TMPXAttribute> attrs;
CleanupClosePushL( attrs );
attrs.AppendL( KMPXMediaGeneralBasic );
attrs.AppendL( KMPXMediaGeneralUri );
attrs.AppendL( KMPXMediaMusicAlbumArtFileName );
attrs.AppendL( KMPXMediaMusicArtist );
attrs.AppendL( KMPXMediaMusicAlbum );
RBufWriteStream writeStream( *buf );
CleanupClosePushL( writeStream );
// externalize attributes array
::ExternalizeL(attrs.Array(), writeStream);
// Close and compress buffer
writeStream.CommitL();
buf->Compress();
CleanupStack::PopAndDestroy( &writeStream );
CleanupStack::PopAndDestroy( &attrs );
TPtrC ptr = MPXUser::Ptr( buf->Ptr( 0 ) );
cmd->SetTextValueL( KMPXCommandMediaAttribute, ptr );
CMPXAttributeSpecs* attrSpecs = CMPXAttributeSpecs::NewL();
CleanupStack::PushL(attrSpecs);
cmd->SetCObjectValueL<CMPXAttributeSpecs>(
KMPXCommandMediaAttributeSpecs, attrSpecs );
CleanupStack::PopAndDestroy(attrSpecs);
iMediaHelper->MediaL( iPlaylist->Path(), cmd, NULL, ETrue, iClientList );
CleanupStack::PopAndDestroy( buf );
// Onwership of media is passed to mediahelper class
CleanupStack::Pop( cmd );
}
#ifdef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API
// ----------------------------------------------------------------------------
// Initialises from file.
// ----------------------------------------------------------------------------
//
EXPORT_C void CMPXPlaybackEngine::Init64L(const RFile64& aFile)
{
MPX_FUNC_EX("CMPXPlaybackEngine::Init64L(const RFile64& aFile)");
iPluginUid = KNullUid; // Reset plugin uid for current item
iInitNext=EFalse;
HandleCloseL();
iPlaySource=EPlayFromFile64;
iNextState=EPbStateNotInitialised;
iFile64.Duplicate(aFile);
TRAPD( err, Init64L(&iFile64) );
if ( KErrNotFound == err )
{
// Mark item as Invalid
MarkItemInvalid( ETrue );
User::Leave( err );
}
}
// ----------------------------------------------------------------------------
// Initialises from file.
// ----------------------------------------------------------------------------
//
EXPORT_C void CMPXPlaybackEngine::InitStreaming64L(const RFile64& aFile, const TInt aAccessPoint)
{
MPX_FUNC_EX("CMPXPlaybackEngine::InitStreaming64L(const RFile64& aFile, const TInt aAccessPoint)");
iPluginUid = KNullUid; // Reset plugin uid for current item
iInitNext=EFalse;
HandleCloseL();
iPlaySource=EPlayFromFile64;
iNextState=EPbStateNotInitialised;
iFile64.Duplicate(aFile);
iAccessPoint = aAccessPoint;
iAccessPointSet = ETrue;
TRAPD( err, Init64L(&iFile64,aAccessPoint));
if ( KErrNotFound == err )
{
// Mark item as Invalid
MarkItemInvalid( ETrue );
User::Leave( err );
}
}
// ----------------------------------------------------------------------------
// Initialise helper method
// ----------------------------------------------------------------------------
//
void CMPXPlaybackEngine::Init64L(RFile64* aFile, TInt aAccessPoint)
{
MPX_FUNC_EX("CMPXPlaybackEngine::Init64L(RFile64* aFile,TInt aAccessPoint)");
CMPXPlaybackPlugin* p( NULL );
if ( iPluginHandler->Plugin() )
{
TRAP_IGNORE(iPluginHandler->Plugin()->CommandL(EPbCmdClose));
}
if (aFile)
{
iPluginHandler->SelectPlayer64L(*aFile);
}
else
{ // should never happen
ASSERT(0);
}
p=iPluginHandler->Plugin();
CheckPtrL(p);
if (p->Uid()!=iPluginUid)
{ // new plugin or new playlist
iPluginUid = p->Uid();
iInitVolume = ETrue;
p->PropertyL( EPbPropertyVolume );
iClientList->SendMsgL(
TMPXPlaybackMessage(TMPXPlaybackMessage::EPlayerChanged));
}
// Stop and close opened file
TRAP_IGNORE(DoStopL(EFalse));
TRAP_IGNORE(p->CommandL(EPbCmdClose));
// If playing from a playlist, send the index as a data
// parameter. This helps performance as the client
// doesn't need to request the index separately
TInt index( KErrNotFound );
if ( EPlayFromCollection == iPlaySource )
{
index = iPlaylist->Index();
}
TMPXPlaybackMessage msg( TMPXPlaybackMessage::EStateChanged,
EPbStateInitialising,
index );
SetStateL( msg );
iProperties[EPbPropertyPosition]=0;
// Check if version2 interface is supported.
CDesCArray* interfaces = iPluginHandler->SupportedInterfacesL( p->Uid() );
TBool version2InterfaceSupported = EFalse;
if (interfaces->MdcaCount())
{
TInt pos(0);
version2InterfaceSupported = !interfaces->FindIsq(KMPXPlaybackPluginVersion2, pos);
}
delete interfaces;
// cast the plugin to use our interface
if (version2InterfaceSupported)
{
CMPXPlaybackPluginVersion2* plugin = NULL;
plugin = static_cast<CMPXPlaybackPluginVersion2*>(p);
// if cast was successful, then init streaming with access point
if (plugin)
{
if ( iAccessPointSet )
{
plugin->InitStreaming64L( *aFile, aAccessPoint );
}
else
{
plugin->Initialise64L( *aFile );
}
}
else
{
MPX_DEBUG1("CMPXPlaybackEngine::Init64L(): -- failure to convert to expected interface");
}
}
else
{
MPX_DEBUG1("CMPXPlaybackEngine::Init64L(): expected interface not supported");
User::Leave( KErrNotFound );
}
}
#endif // SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API
// End of file