diff -r 000000000000 -r 71ca22bcf22a mmfenh/progressivedownload/ProgressiveDownloadUtility/src/PDProperties.cpp --- /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) && iAttemptsToOpenSetFileSize(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(); + }