diff -r 000000000000 -r a2952bb97e68 mpx/playbackframework/playbackengine/src/mpxplaybackengine.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mpx/playbackframework/playbackengine/src/mpxplaybackengine.cpp Thu Dec 17 08:55:47 2009 +0200 @@ -0,0 +1,3868 @@ +/* +* 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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( + 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 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(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(KMPXCommandGeneralId); + switch (id) + { + case KMPXCommandIdPlaybackGeneral: + { + ASSERT(aCmd.IsSupported(KMPXCommandPlaybackGeneralType)); + TMPXPlaybackCommand cmd = static_cast( + aCmd.ValueTObjectL(KMPXCommandPlaybackGeneralType)); + if ( EPbCmdPlay == cmd || + EPbCmdPlayPause == cmd || + EPbCmdStop == cmd) + { + ASSERT(aCmd.IsSupported(KMPXCommandPlaybackGeneralClientPid)); + iLastActiveProcess = aCmd.ValueTObjectL( + KMPXCommandPlaybackGeneralClientPid); + } + else if (EPbCmdStop == cmd) + { + ASSERT(aCmd.IsSupported(KMPXCommandPlaybackGeneralClientPid)); + iLastInactiveProcess = aCmd.ValueTObjectL( + KMPXCommandPlaybackGeneralClientPid); + } + TInt data(0); + if (aCmd.IsSupported(KMPXCommandPlaybackGeneralData)) + { + data = aCmd.ValueTObjectL(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( + 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( 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( 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(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(aValue); + if( iProperties[EPbPropertyRepeatMode] != repeat ) + { + iProperties[EPbPropertyRepeatMode] = repeat; + if (iPlaySource==EPlayFromCollection && iPlaylist) + { + CMPXCollectionPlaylist::TRepeatMode repeatmode = + static_cast( + 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( 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(KMPXMessageGeneral); + HBufC* path = reinterpret_cast(aData); + msg->SetTObjectValueL(KMPXMessageGeneralId, id); + msg->SetTObjectValueL(KMPXMessageGeneralEvent, TMPXPlaybackMessage::EDownloadFileMoved); + msg->SetTObjectValueL(KMPXMessageGeneralType, 0); + msg->SetTObjectValueL(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(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(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( KMPXMediaGeneralId ); + MPX_DEBUG3("CMPXPlaybackEngine::HandleCollectionMediaL iItemId %d %d", iItemId.iId1, iItemId.iId2); + } + + iDbFlag = 0; + if ( aMedia.IsSupported( KMPXMediaGeneralFlags )) + { + iDbFlag = aMedia.ValueTObjectL( KMPXMediaGeneralFlags ); + MPX_DEBUG2("CMPXPlaybackEngine::HandleCollectionMediaL iDbFlag %x", iDbFlag); + } + + iMediaDuration = 0; + if ( aMedia.IsSupported( KMPXMediaGeneralDuration )) + { + iMediaDuration = aMedia.ValueTObjectL( KMPXMediaGeneralDuration ); + MPX_DEBUG2("CMPXPlaybackEngine::HandleCollectionMediaL iMediaDuration %d", iMediaDuration); + } + + iAccessPoint = 0; + iAccessPointSet = EFalse; + if ( aMedia.IsSupported(KMPXMediaGeneralExtAccessPoint) ) + { + iAccessPoint = aMedia.ValueTObjectL( 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(KMPXMessageGeneralId, aMessageId); + msg->SetTObjectValueL(KMPXAttrPluginId, aPluginUid); + msg->SetTObjectValueL(KMPXAttrPluginLoaded, aLoaded); + if (aVersion > 0) + { + msg->SetTObjectValueL(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( 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(aCallback); + } + CMPXPlaybackPlugin* p = aPtrData ? + static_cast(aPtrData) : + iPluginHandler->Plugin(); + switch(aTask) + { + case EProperty: + { + CheckPtrL(p); + p->PropertyL(static_cast(aParamData)); + break; + } + case EMedia: + { + iMediaAttrs.Reset(); + CMPXCommand* cmd( static_cast(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( 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(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 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( 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(KMPXMediaGeneralId, iItemId); + } + else if (iUri) + { + media->SetTextValueL( KMPXMediaGeneralUri, *iUri); + } + else + { + media->SetTObjectValueL( 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(KMPXCommandGeneralId, KMPXCommandContentIdMedia); + CBufBase* buf = CBufFlat::NewL( KMPXBufGranularity ); + CleanupStack::PushL( buf ); + + // Setup array buffer + RArray 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( + 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(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