--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mmfenh/progressivedownload/ProgressiveDownloadUtility/src/PDProperties.cpp Tue Feb 02 01:08:46 2010 +0200
@@ -0,0 +1,446 @@
+/*
+* Copyright (c) 2004 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: Progressive Download Utility
+*
+*/
+
+
+
+#include "PdProperties.h"
+
+//Percentage (increments) of the file [TBD]
+//that needs to be downloaded/buffered before playing begins
+//Should try at 25%,50%,75%,100%
+const TInt KPercentageToBufferIncrement =25;
+
+
+//Percentage of the file needed for header [TBD]
+//const TInt KPercentageNeededForHeader = 33;
+const TInt KBytesNeededForHeader = 200000;//102400;
+
+//const TInt KMinFileSize = 100000;
+
+//Max attempts to openfile
+const TInt KRetryOpen = 1;
+
+
+//===============================================================
+// CPdProperties implementation begins
+//
+//===============================================================
+EXPORT_C CPdProperties* CPdProperties::NewL()
+ {
+ CPdProperties* self = new(ELeave) CPdProperties();
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+EXPORT_C CPdProperties* CPdProperties::NewLC()
+ {
+ CPdProperties* self = new (ELeave) CPdProperties();
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ return self;
+ }
+
+EXPORT_C CPdProperties::~CPdProperties()
+ {
+ delete iFileName;
+
+ }
+
+void CPdProperties::ConstructL()
+ {
+
+ iFileOpened = EFalse;
+ iAttemptsToOpen = 0;
+ iState = EStopped;
+ iPercentageToBuffer= KPercentageToBufferIncrement;
+ iDownloadCompleted = EFalse;
+ iFileBytePosition = 0;
+ iTimePosition = 0;
+ iBytesDownloaded = 0;
+ iOpenInProgress = EFalse;
+
+ }
+
+CPdProperties::CPdProperties()
+ {
+
+ }
+
+EXPORT_C CAudioPdPlayUtility* CPdProperties::OpenL(const TDesC& aFileName,
+ MAudioPdPlayUtilityCallback& aCallback)
+ {
+ iUseFileHandle = EFalse;
+ iFileName = HBufC::NewL ( aFileName.Length() );
+ iFileName->Des().Copy( aFileName );
+
+ iCallback = &aCallback;
+
+ iAudioPdPlayUtility = CAudioPdPlayUtility::NewL(*this);
+
+ return iAudioPdPlayUtility;
+ }
+
+EXPORT_C CAudioPdPlayUtility* CPdProperties::OpenL(const RFile& aFileHandle,
+ MAudioPdPlayUtilityCallback& aCallback)
+ {
+ iUseFileHandle = ETrue;
+ iFileHandle.Duplicate(aFileHandle);
+
+ iCallback = &aCallback;
+
+ iAudioPdPlayUtility = CAudioPdPlayUtility::NewL(*this);
+
+
+ return iAudioPdPlayUtility;
+ }
+
+
+void CPdProperties::HandleDownloadEventL(TUint /*aTransactionID*/,
+ TBrCtlDownloadEvent aEvent,
+ TUint aValue)
+ {
+/*
+Event Value (optional) Comment
+EDownloadEventStarted Total Bytes Size of content as specified in header.
+EDownloadEventCompleted Total Bytes Received Total number received should be same as specified at start.
+EDownloadEventProgress Bytes Received Number of bytes received so far. May be used to determine % received for progress bar. This will be sent multiple times. Frequency to be determined. Perhaps on every chunk received.
+EDownloadEventCanceled N/A Cancelled by Download Manager
+EDownloadEventError N/A Cancelled by BrowserEngine due to network/http error.
+EDownloadEventPaused, aValue is the size downloaded so far
+EDownloadEventResumed, aValue is the size downloaded
+EDownloadEventPausable aValue = true when it is pausable
+*/
+
+ switch (aEvent)
+ {
+ case EDownloadEventStarted: //Started
+ {
+ if(aValue)
+ iFileSize = aValue;
+ break;
+ }
+
+ case EDownloadEventCompleted: //Completed
+ {
+ iDownloadCompleted = ETrue;
+ iBytesDownloaded = aValue;
+
+ if((!iFileOpened) && (!iOpenInProgress))
+ {
+ //Used for when metadata is at the end of file
+ //or when the file is in cache and already downloaded.
+ iAudioPdPlayUtility->SetFileSize(iFileSize);
+ iAudioPdPlayUtility->SetBytesDownloaded(iBytesDownloaded, iDownloadCompleted);
+ iAudioPdPlayUtility->DlCompleteOpenFileL(iFileName->Des());
+ iOpenInProgress = ETrue;
+ iAttemptsToOpen++;
+ }
+ break;
+ }
+
+ case EDownloadEventProgress: //Progress
+ {
+ if(aValue)
+ iBytesDownloaded = aValue;
+ break;
+ }
+ case EDownloadEventCanceled: //Cancelled
+ case EDownloadEventError: //Error
+ {
+ iBytesDownloaded = 0;
+ iFileSize = 0;
+ break;
+ }
+
+ case EDownloadEventPaused: //Paused
+ case EDownloadEventResumed: //Resumed
+ case EDownloadEventPausable: //Pausable
+ //do nothing
+ break;
+
+ default:
+ break;
+
+ } // switch(aEvent)
+
+
+ #if _DEBUG
+ RDebug::Print(_L("CPdProperties::HandleDownloadEventL"));
+ RDebug::Print(_L("file byte position %d"),iFileBytePosition);
+ RDebug::Print(_L("bytes downloaded %d"),iBytesDownloaded);
+ RDebug::Print(_L("file size %d"),iFileSize);
+ RDebug::Print(_L("percentage to buffer %d"),iPercentageToBuffer);
+ RDebug::Print(_L("download state %d"),aEvent);
+ #endif
+
+ HandleDownloadUpdateL();
+ }
+
+TInt CPdProperties::CalculatePercentageDownloaded()
+ {
+ TInt percentageDone = 0;
+ if((iFileSize>0) && (iBytesDownloaded>0))
+ percentageDone= ((100*iBytesDownloaded)/iFileSize);
+
+ return percentageDone;
+ }
+
+void CPdProperties::SavePosition()
+ {
+ #if _DEBUG
+ RDebug::Print(_L("CPdProperties::SavePosition"));
+ #endif
+ TTimeIntervalMicroSeconds timeposition;
+ if(iState==EPlaying)
+ {
+ iAudioPdPlayUtility->GetFilePosition(iFileBytePosition);
+
+ iAudioPdPlayUtility->GetPosition(timeposition);
+ if(timeposition >iTimePosition)
+ iTimePosition = timeposition;
+ }
+
+ #if _DEBUG
+ RDebug::Print(_L("CPdProperties::SavePosition iTimePosition %d"),I64INT(iTimePosition.Int64()));
+ #endif
+
+ }
+
+void CPdProperties::HandleDownloadUpdateL()
+ {
+ TInt percentageDone=0;
+
+ percentageDone = CalculatePercentageDownloaded();
+
+ #if _DEBUG
+ RDebug::Print(_L("iFileOpened %d "),iFileOpened);
+ RDebug::Print(_L("iState %d "),iState);
+ RDebug::Print(_L("percentage downloaded %d "),percentageDone);
+ RDebug::Print(_L("iBytesDownloaded %d "),iBytesDownloaded);
+ RDebug::Print(_L("iAttemptsToOpen %d "),iAttemptsToOpen);
+ RDebug::Print(_L("iOpenInProgress %d "),iOpenInProgress);
+ RDebug::Print(_L("iFileSize %d "),iFileSize);
+ #endif
+ //if((percentageDone>KPercentageNeededForHeader)&&
+ if((iBytesDownloaded>KBytesNeededForHeader)&&
+ (!iFileOpened) && iAttemptsToOpen<KRetryOpen && (!iOpenInProgress))
+ {
+ TInt err(KErrNone);
+ if(iUseFileHandle)
+ {
+#ifdef RD_PD_FOR_AUDIO_CONTENT_VIA_HELIX_ENGINE
+ iAudioPdPlayUtility->SetFileSize(iFileSize);
+#endif
+ iAudioPdPlayUtility->OpenFileL(iFileHandle);
+ }
+ else
+ {
+#ifdef RD_PD_FOR_AUDIO_CONTENT_VIA_HELIX_ENGINE
+ iAudioPdPlayUtility->SetFileSize(iFileSize);
+#endif
+ TRAP(err,iAudioPdPlayUtility->OpenFileL(iFileName->Des()));
+ }
+
+ if(err != KErrNone)
+ {
+ MapcInitComplete(err,0);
+ return;
+ }
+ iOpenInProgress = ETrue;
+ iAttemptsToOpen++;
+
+ }
+
+ //Pass bytes downloaded to ProgressiveDownload DataSource
+ iAudioPdPlayUtility->SetBytesDownloaded(iBytesDownloaded, iDownloadCompleted);
+
+ if(iFileOpened)
+ {//if the file is opened/playing save the
+ //file byte position and the time position
+ SavePosition();
+ switch (iState)
+ {
+ case EPlaying:
+ {
+ if((iFileBytePosition >=iBytesDownloaded) &&
+ (percentageDone<=100))
+ {
+ //Should have paused, but is causing problems
+ //with DRM1 FL
+ #if _DEBUG
+ RDebug::Print(_L("Should have paused"));
+ #endif
+ //StartPaused();
+ }
+ break;
+ }
+ // Try to automatically resume only if we are stopped due to lac
+ // of data (KErrUnderflow)
+ //case EPaused:
+ //case EStopped:
+ case EStoppedAutoResume:
+ {
+ //if stopped attempt to play at 25%,50%,75%,100%
+ if( percentageDone >= iPercentageToBuffer )
+ {
+ StartPlaying();
+ }
+ break;
+ }
+ default:
+ break;
+ }//switch iState
+
+ if( percentageDone > iPercentageToBuffer )
+ {
+ iPercentageToBuffer += KPercentageToBufferIncrement;
+ }
+ }//iFileOpened
+
+ }
+
+/*
+void CPdProperties::StartPaused()
+ {
+ #if _DEBUG
+ RDebug::Print(_L("ProgressiveDownload audio paused"));
+ #endif
+ iState = EPaused;
+ iAudioPdPlayUtility->Pause(); //Audio Pause
+ //iCallback->Paused();
+ }
+*/
+
+void CPdProperties::StartPlaying()
+ {
+ #if _DEBUG
+ RDebug::Print(_L("ProgressiveDownload audio play"));
+ #endif
+
+ //Will disable automatic play if manual play was started.
+ TInt state = iAudioPdPlayUtility->CheckAudioPlayerState();
+
+ if(iState!=EPlaying)
+ {
+ iState = EPlaying;
+
+ TTimeIntervalMicroSeconds timeposition(0);
+ TInt error = iAudioPdPlayUtility->GetPosition(timeposition);
+
+ #if _DEBUG
+ RDebug::Print(_L("ProgressiveDownload SetPosition SavePos[%d] CurPos[%d]"), I64INT(iTimePosition.Int64()),I64INT(timeposition.Int64()));
+ #endif
+
+ if(timeposition != iTimePosition)
+ {
+ iAudioPdPlayUtility->SetPosition(iTimePosition);
+ }
+
+ iAudioPdPlayUtility->Play();
+ //iCallback->Playing();
+ }
+ }
+
+//From MMdaAudioPlayerCallback
+void CPdProperties::MapcInitComplete(TInt aError, const TTimeIntervalMicroSeconds& aDuration)
+ {
+
+#if _DEBUG
+ RDebug::Print(_L("ProgressiveDownload file opened err =%d"),aError);
+#endif
+ //iError = aError;
+ iOpenInProgress = EFalse;
+
+ iState = EStopped;
+
+ if( aError == KErrNone )
+ {
+ if( aDuration > 0 )
+ {
+ iFileOpened = ETrue;
+ }
+ else
+ {
+#if _DEBUG
+ RDebug::Print(_L("ProgressiveDownload - Open failed - could not calculate duration"));
+ RDebug::Print(_L("metadata is at the end of file PD not supported"));
+#endif
+ iFileOpened = EFalse;
+ return;
+ }
+
+ if( iFileSize > 0 )
+ {
+ TInt err = iAudioPdPlayUtility->SetFileSize(iFileSize);
+#if _DEBUG
+ RDebug::Print(_L("CPdProperties::SetFileSize=%d err %d"),iFileSize,err);
+#endif
+ }
+ // After init is complete successfully, playback is to be started
+ // automatically.
+ iState = EStoppedAutoResume;
+ }
+ iCallback->MapcInitComplete(aError,aDuration);
+
+ //Last chance to automatically play a file with very fast download
+ //or when the file is in cache and there are only a couple of download events.
+ if ( (iDownloadCompleted) && (aError == KErrNone ) )
+ {
+ StartPlaying();
+ }
+ }
+
+void CPdProperties::MapcPlayComplete(TInt aError)
+ {
+#if _DEBUG
+ RDebug::Print(_L("ProgressiveDownload play complete err=%d"),aError);
+#endif
+ //iError = aError;
+ // Playback stopped due to lac of data (KErrUnderflow)
+ if( aError == KErrUnderflow )
+ {// By now, Controller would've gone to STOPPED state and would've reset
+ // play position to zero. There is no point in querying position here.
+ TTimeIntervalMicroSeconds timeposition;
+ TInt error = iAudioPdPlayUtility->GetPosition(timeposition);
+ if(timeposition > iTimePosition)
+ {
+ iTimePosition = timeposition;
+ }
+#if _DEBUG
+ RDebug::Print(_L("ProgressiveDownload GetPosition return [%d] error[%d]"), I64INT(iTimePosition.Int64()), error);
+#endif
+ iState = EStoppedAutoResume;
+ iCallback->Paused();
+ }
+ else
+ {
+ iState = EStopped;
+ iCallback->MapcPlayComplete(aError);
+ }
+ }
+
+void CPdProperties::Playing()
+ {
+ iCallback->Playing();
+ }
+
+void CPdProperties::Paused()
+ {
+ iCallback->Paused();
+ }