mmfenh/progressivedownload/ProgressiveDownloadUtility/src/PDProperties.cpp
changeset 16 43d09473c595
parent 14 80975da52420
child 22 128eb6a32b84
equal deleted inserted replaced
14:80975da52420 16:43d09473c595
     1 /*
       
     2 * Copyright (c) 2004 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  Progressive Download Utility
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 #include "PdProperties.h"
       
    21 
       
    22 //Percentage (increments) of the file [TBD]
       
    23 //that needs to be downloaded/buffered before playing begins
       
    24 //Should try at 25%,50%,75%,100%
       
    25 const TInt KPercentageToBufferIncrement =25;
       
    26 
       
    27 
       
    28 //Percentage of the file needed for header [TBD]
       
    29 //const TInt KPercentageNeededForHeader = 33;
       
    30 const TInt KBytesNeededForHeader = 200000;//102400;
       
    31 
       
    32 //const TInt KMinFileSize = 100000;
       
    33 
       
    34 //Max attempts to openfile
       
    35 const TInt KRetryOpen = 1;
       
    36 
       
    37 
       
    38 //===============================================================
       
    39 // CPdProperties implementation begins
       
    40 //
       
    41 //===============================================================
       
    42 EXPORT_C CPdProperties* CPdProperties::NewL()
       
    43     {
       
    44     CPdProperties* self = new(ELeave) CPdProperties();
       
    45     CleanupStack::PushL(self);
       
    46     self->ConstructL();
       
    47     CleanupStack::Pop(self);
       
    48     return self;
       
    49     }
       
    50 
       
    51 EXPORT_C CPdProperties* CPdProperties::NewLC()
       
    52     {
       
    53     CPdProperties* self = new (ELeave) CPdProperties();
       
    54     CleanupStack::PushL(self);
       
    55     self->ConstructL();
       
    56     return self;
       
    57     }
       
    58 
       
    59 EXPORT_C CPdProperties::~CPdProperties()
       
    60     {
       
    61     delete iFileName;
       
    62 
       
    63     }
       
    64 
       
    65 void CPdProperties::ConstructL()
       
    66     {
       
    67 
       
    68     iFileOpened        = EFalse;
       
    69     iAttemptsToOpen    = 0;
       
    70     iState             = EStopped;
       
    71     iPercentageToBuffer= KPercentageToBufferIncrement;
       
    72     iDownloadCompleted = EFalse;
       
    73     iFileBytePosition  = 0;
       
    74     iTimePosition      = 0;
       
    75     iBytesDownloaded   = 0;
       
    76     iOpenInProgress    = EFalse;
       
    77 
       
    78     }
       
    79 
       
    80 CPdProperties::CPdProperties()
       
    81     {
       
    82 
       
    83     }
       
    84 
       
    85 EXPORT_C CAudioPdPlayUtility* CPdProperties::OpenL(const TDesC& aFileName,
       
    86                                           MAudioPdPlayUtilityCallback& aCallback)
       
    87     {
       
    88     iUseFileHandle = EFalse;
       
    89     iFileName = HBufC::NewL ( aFileName.Length() );
       
    90     iFileName->Des().Copy( aFileName );
       
    91 
       
    92     iCallback = &aCallback;
       
    93 
       
    94     iAudioPdPlayUtility = CAudioPdPlayUtility::NewL(*this);
       
    95 
       
    96     return iAudioPdPlayUtility;
       
    97     }
       
    98 
       
    99 EXPORT_C CAudioPdPlayUtility* CPdProperties::OpenL(const RFile& aFileHandle,
       
   100                                           MAudioPdPlayUtilityCallback& aCallback)
       
   101     {
       
   102     iUseFileHandle = ETrue;
       
   103     iFileHandle.Duplicate(aFileHandle);
       
   104 
       
   105     iCallback = &aCallback;
       
   106 
       
   107     iAudioPdPlayUtility = CAudioPdPlayUtility::NewL(*this);
       
   108 
       
   109 
       
   110     return iAudioPdPlayUtility;
       
   111     }
       
   112 
       
   113 
       
   114 void CPdProperties::HandleDownloadEventL(TUint /*aTransactionID*/,
       
   115                                          TBrCtlDownloadEvent aEvent,
       
   116                                          TUint aValue)
       
   117     {
       
   118 /*
       
   119 Event                    Value (optional)       Comment
       
   120 EDownloadEventStarted     Total Bytes           Size of content as specified in header.
       
   121 EDownloadEventCompleted   Total Bytes Received  Total number received should be same as specified at start.
       
   122 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.
       
   123 EDownloadEventCanceled    N/A                   Cancelled by Download Manager
       
   124 EDownloadEventError       N/A                   Cancelled by BrowserEngine due to network/http error.
       
   125 EDownloadEventPaused,                           aValue is the size downloaded so far
       
   126 EDownloadEventResumed,                          aValue is the size downloaded
       
   127 EDownloadEventPausable                          aValue = true when it is pausable
       
   128 */
       
   129 
       
   130     switch (aEvent)
       
   131         {
       
   132         case EDownloadEventStarted: //Started
       
   133            {
       
   134            if(aValue)
       
   135              iFileSize = aValue;
       
   136            break;
       
   137            }
       
   138 
       
   139         case EDownloadEventCompleted: //Completed
       
   140            {
       
   141            iDownloadCompleted = ETrue;
       
   142            iBytesDownloaded = aValue;
       
   143 
       
   144            if((!iFileOpened) && (!iOpenInProgress))
       
   145               {
       
   146               //Used for when metadata is at the end of file
       
   147               //or when the file is in cache and already downloaded.
       
   148               iAudioPdPlayUtility->SetFileSize(iFileSize);
       
   149               iAudioPdPlayUtility->SetBytesDownloaded(iBytesDownloaded, iDownloadCompleted);
       
   150               iAudioPdPlayUtility->DlCompleteOpenFileL(iFileName->Des());
       
   151               iOpenInProgress = ETrue;
       
   152               iAttemptsToOpen++;
       
   153               }
       
   154            break;
       
   155            }
       
   156 
       
   157         case EDownloadEventProgress: //Progress
       
   158            {
       
   159            if(aValue)
       
   160              iBytesDownloaded = aValue;
       
   161            break;
       
   162            }
       
   163         case EDownloadEventCanceled: //Cancelled
       
   164         case EDownloadEventError: //Error
       
   165             {
       
   166             iBytesDownloaded = 0;
       
   167             iFileSize = 0;
       
   168             break;
       
   169             }
       
   170 
       
   171         case EDownloadEventPaused:   //Paused
       
   172         case EDownloadEventResumed:  //Resumed
       
   173         case EDownloadEventPausable: //Pausable
       
   174            //do nothing
       
   175         break;
       
   176 
       
   177         default:
       
   178         break;
       
   179 
       
   180         } // switch(aEvent)
       
   181 
       
   182 
       
   183     #if _DEBUG
       
   184        RDebug::Print(_L("CPdProperties::HandleDownloadEventL"));
       
   185        RDebug::Print(_L("file byte position     %d"),iFileBytePosition);
       
   186        RDebug::Print(_L("bytes downloaded       %d"),iBytesDownloaded);
       
   187        RDebug::Print(_L("file size              %d"),iFileSize);
       
   188        RDebug::Print(_L("percentage to buffer   %d"),iPercentageToBuffer);
       
   189        RDebug::Print(_L("download state         %d"),aEvent);
       
   190     #endif
       
   191 
       
   192     HandleDownloadUpdateL();
       
   193     }
       
   194 
       
   195 TInt CPdProperties::CalculatePercentageDownloaded()
       
   196     {
       
   197     TInt percentageDone = 0;
       
   198     if((iFileSize>0) && (iBytesDownloaded>0))
       
   199        percentageDone= ((100*iBytesDownloaded)/iFileSize);
       
   200 
       
   201     return percentageDone;
       
   202     }
       
   203 
       
   204 void CPdProperties::SavePosition()
       
   205     {
       
   206     #if _DEBUG
       
   207       RDebug::Print(_L("CPdProperties::SavePosition"));
       
   208     #endif
       
   209     TTimeIntervalMicroSeconds timeposition;
       
   210     if(iState==EPlaying)
       
   211         {
       
   212         iAudioPdPlayUtility->GetFilePosition(iFileBytePosition);
       
   213 
       
   214         iAudioPdPlayUtility->GetPosition(timeposition);
       
   215         if(timeposition >iTimePosition)
       
   216            iTimePosition = timeposition;
       
   217         }
       
   218 
       
   219     #if _DEBUG
       
   220       RDebug::Print(_L("CPdProperties::SavePosition iTimePosition %d"),I64INT(iTimePosition.Int64()));
       
   221     #endif
       
   222 
       
   223     }
       
   224 
       
   225 void CPdProperties::HandleDownloadUpdateL()
       
   226     {
       
   227     TInt percentageDone=0;
       
   228 
       
   229     percentageDone = CalculatePercentageDownloaded();
       
   230 
       
   231     #if _DEBUG
       
   232         RDebug::Print(_L("iFileOpened %d "),iFileOpened);
       
   233         RDebug::Print(_L("iState  %d "),iState);
       
   234         RDebug::Print(_L("percentage downloaded %d "),percentageDone);
       
   235         RDebug::Print(_L("iBytesDownloaded %d "),iBytesDownloaded);
       
   236         RDebug::Print(_L("iAttemptsToOpen  %d "),iAttemptsToOpen);
       
   237         RDebug::Print(_L("iOpenInProgress %d "),iOpenInProgress);
       
   238         RDebug::Print(_L("iFileSize %d "),iFileSize);
       
   239     #endif
       
   240     //if((percentageDone>KPercentageNeededForHeader)&&
       
   241     if((iBytesDownloaded>KBytesNeededForHeader)&&
       
   242       (!iFileOpened) && iAttemptsToOpen<KRetryOpen && (!iOpenInProgress))
       
   243         {
       
   244         TInt err(KErrNone);
       
   245         if(iUseFileHandle)
       
   246             {
       
   247 #ifdef RD_PD_FOR_AUDIO_CONTENT_VIA_HELIX_ENGINE
       
   248             iAudioPdPlayUtility->SetFileSize(iFileSize);
       
   249 #endif
       
   250             iAudioPdPlayUtility->OpenFileL(iFileHandle);
       
   251             }
       
   252         else
       
   253             {
       
   254 #ifdef RD_PD_FOR_AUDIO_CONTENT_VIA_HELIX_ENGINE
       
   255             iAudioPdPlayUtility->SetFileSize(iFileSize);
       
   256 #endif
       
   257             TRAP(err,iAudioPdPlayUtility->OpenFileL(iFileName->Des()));
       
   258             }
       
   259 
       
   260         if(err != KErrNone)
       
   261             {
       
   262             MapcInitComplete(err,0);
       
   263             return;
       
   264             }
       
   265         iOpenInProgress = ETrue;
       
   266         iAttemptsToOpen++;
       
   267 
       
   268         }
       
   269 
       
   270     //Pass bytes downloaded to ProgressiveDownload DataSource
       
   271     iAudioPdPlayUtility->SetBytesDownloaded(iBytesDownloaded, iDownloadCompleted);
       
   272 
       
   273     if(iFileOpened)
       
   274         {//if the file is opened/playing save the
       
   275         //file byte position and the time position
       
   276         SavePosition();
       
   277         switch (iState)
       
   278             {
       
   279             case EPlaying:
       
   280                 {
       
   281                 if((iFileBytePosition >=iBytesDownloaded) &&
       
   282                    (percentageDone<=100))
       
   283                     {
       
   284                     //Should have paused, but is causing problems
       
   285                     //with DRM1 FL
       
   286                     #if _DEBUG
       
   287                       RDebug::Print(_L("Should have paused"));
       
   288                     #endif
       
   289                     //StartPaused();
       
   290                     }
       
   291                 break;
       
   292                 }
       
   293             // Try to automatically resume only if we are stopped due to lac
       
   294             // of data (KErrUnderflow)
       
   295             //case EPaused:
       
   296             //case EStopped:
       
   297             case EStoppedAutoResume:
       
   298                 {
       
   299                 //if stopped attempt to play at 25%,50%,75%,100%
       
   300                 if( percentageDone >= iPercentageToBuffer )
       
   301                     {
       
   302                     StartPlaying();
       
   303                     }
       
   304                 break;
       
   305                 }
       
   306             default:
       
   307                 break;
       
   308             }//switch iState
       
   309 
       
   310         if( percentageDone > iPercentageToBuffer )
       
   311             {
       
   312             iPercentageToBuffer += KPercentageToBufferIncrement;
       
   313             }
       
   314         }//iFileOpened
       
   315 
       
   316     }
       
   317 
       
   318 /*
       
   319 void CPdProperties::StartPaused()
       
   320     {
       
   321     #if _DEBUG
       
   322        RDebug::Print(_L("ProgressiveDownload audio paused"));
       
   323     #endif
       
   324     iState = EPaused;
       
   325     iAudioPdPlayUtility->Pause(); //Audio Pause
       
   326     //iCallback->Paused();
       
   327     }
       
   328 */
       
   329 
       
   330 void CPdProperties::StartPlaying()
       
   331     {
       
   332     #if _DEBUG
       
   333        RDebug::Print(_L("ProgressiveDownload audio play"));
       
   334     #endif
       
   335 
       
   336     //Will disable automatic play if manual play was started.
       
   337     TInt state = iAudioPdPlayUtility->CheckAudioPlayerState();
       
   338 
       
   339     if(iState!=EPlaying)
       
   340         {
       
   341         iState = EPlaying;
       
   342 
       
   343         TTimeIntervalMicroSeconds timeposition(0);
       
   344         TInt error = iAudioPdPlayUtility->GetPosition(timeposition);
       
   345 
       
   346     #if _DEBUG
       
   347        RDebug::Print(_L("ProgressiveDownload SetPosition SavePos[%d] CurPos[%d]"), I64INT(iTimePosition.Int64()),I64INT(timeposition.Int64()));
       
   348     #endif
       
   349 
       
   350         if(timeposition != iTimePosition)
       
   351         {
       
   352         iAudioPdPlayUtility->SetPosition(iTimePosition);
       
   353         }
       
   354 
       
   355         iAudioPdPlayUtility->Play();
       
   356         //iCallback->Playing();
       
   357         }
       
   358     }
       
   359 
       
   360 //From MMdaAudioPlayerCallback
       
   361 void CPdProperties::MapcInitComplete(TInt aError, const TTimeIntervalMicroSeconds& aDuration)
       
   362     {
       
   363 
       
   364 #if _DEBUG
       
   365    RDebug::Print(_L("ProgressiveDownload file opened err =%d"),aError);
       
   366 #endif
       
   367     //iError = aError;
       
   368     iOpenInProgress = EFalse;
       
   369 
       
   370     iState = EStopped;
       
   371 
       
   372     if( aError == KErrNone )
       
   373         {
       
   374         if( aDuration > 0 )
       
   375             {
       
   376             iFileOpened = ETrue;
       
   377             }
       
   378         else
       
   379             {
       
   380 #if _DEBUG
       
   381             RDebug::Print(_L("ProgressiveDownload - Open failed - could not calculate duration"));
       
   382             RDebug::Print(_L("metadata is at the end of file PD not supported"));
       
   383 #endif
       
   384             iFileOpened = EFalse;
       
   385             return;
       
   386             }
       
   387 
       
   388         if( iFileSize > 0 )
       
   389             {
       
   390             TInt err = iAudioPdPlayUtility->SetFileSize(iFileSize);
       
   391 #if _DEBUG
       
   392             RDebug::Print(_L("CPdProperties::SetFileSize=%d err %d"),iFileSize,err);
       
   393 #endif
       
   394             }
       
   395         // After init is complete successfully, playback is to be started
       
   396         // automatically.
       
   397         iState = EStoppedAutoResume;
       
   398         }
       
   399     iCallback->MapcInitComplete(aError,aDuration);
       
   400 
       
   401     //Last chance to automatically play a file with very fast download
       
   402     //or when the file is in cache and there are only a couple of download events.
       
   403     if ( (iDownloadCompleted) && (aError == KErrNone ) )
       
   404         {
       
   405         StartPlaying();
       
   406         }
       
   407     }
       
   408 
       
   409 void CPdProperties::MapcPlayComplete(TInt aError)
       
   410     {
       
   411 #if _DEBUG
       
   412     RDebug::Print(_L("ProgressiveDownload play complete err=%d"),aError);
       
   413 #endif
       
   414     //iError = aError;
       
   415     // Playback stopped due to lac of data (KErrUnderflow)
       
   416     if( aError == KErrUnderflow )
       
   417         {// By now, Controller would've gone to STOPPED state and would've reset
       
   418         // play position to zero. There is no point in querying position here.
       
   419         TTimeIntervalMicroSeconds timeposition;
       
   420         TInt error = iAudioPdPlayUtility->GetPosition(timeposition);
       
   421         if(timeposition > iTimePosition)
       
   422             {
       
   423             iTimePosition = timeposition;
       
   424             }
       
   425 #if _DEBUG
       
   426         RDebug::Print(_L("ProgressiveDownload GetPosition return [%d] error[%d]"), I64INT(iTimePosition.Int64()), error);
       
   427 #endif
       
   428         iState = EStoppedAutoResume;
       
   429         iCallback->Paused();
       
   430         }
       
   431     else
       
   432         {
       
   433         iState = EStopped;
       
   434         iCallback->MapcPlayComplete(aError);
       
   435         }
       
   436     }
       
   437 
       
   438 void CPdProperties::Playing()
       
   439     {
       
   440     iCallback->Playing();
       
   441     }
       
   442 
       
   443 void CPdProperties::Paused()
       
   444     {
       
   445     iCallback->Paused();
       
   446     }