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