controlpanelui/src/tonefetcher/tonefetcherengine/private/CTonePlayer.cpp
branchRCL_3
changeset 13 90fe62538f66
equal deleted inserted replaced
12:3fec62e6e7fc 13:90fe62538f66
       
     1 /*
       
     2  * Copyright (c) 2009 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:
       
    15  *     The source file for tone playing.
       
    16  *     
       
    17  */
       
    18 #include "CTonePlayer.h"
       
    19 #include "tonefetcherutils.h"
       
    20 #include <AudioPreference.h>             // KAudioPriorityPreview
       
    21 #include <c3dringingtoneinterface.h>     // C3DRingingToneInterface
       
    22 #include <ctsydomainpskeys.h>            // for phone call states
       
    23 #include <MProfileEngine.h>
       
    24 #include <MProfile.h>
       
    25 #include <MProfileTones.h>
       
    26 #include "TProfileToneSettings.h"
       
    27 #include <MProfileExtraSettings.h>
       
    28 #include <MProfile3DToneSettings.h>
       
    29 #include <ProfileInternal.hrh>
       
    30 #include <ProfileEngineDomainCRKeys.h>   // KProEngDefaultRingingTone
       
    31 #include "MTonePlayingWatcher.h"
       
    32 
       
    33 
       
    34 CMFPreviewHandlerBase::CMFPreviewHandlerBase()
       
    35     {
       
    36     iMediaType = KErrNotFound;
       
    37     iRingingVolume = KErrNotFound;
       
    38     iRingingType = KErrNotFound;
       
    39     iVibra = KErrNotFound;
       
    40     i3DEffect = KErrNotFound;
       
    41     i3DEcho = KErrNotFound;
       
    42     iFileSize = KErrNotFound;    
       
    43     iFullName = 0;    
       
    44     iActiveProfileRead = EFalse;
       
    45     iPlayerStatus = EPlayerNotCreated;
       
    46 
       
    47     }
       
    48 
       
    49 void CMFPreviewHandlerBase::ConstructL()
       
    50     {
       
    51     // To allow/not allow screensaver
       
    52     // Errors ignored, no actions needed if API is not available
       
    53     //iProperty.Attach( KPSUidScreenSaver, KScreenSaverAllowScreenSaver );    
       
    54     TRAP_IGNORE(User::LeaveIfError( iApaSession.Connect() ) );
       
    55     
       
    56     TRAP_IGNORE( ReadDefaultToneL() );
       
    57     // To keep backlight on while a video is being previewed
       
    58     iBacklightTimer = CPeriodic::NewL( EPriorityLow );
       
    59     }
       
    60 
       
    61 CMFPreviewHandlerBase::~CMFPreviewHandlerBase()
       
    62     {
       
    63     delete iFullName;
       
    64     iProperty.Close();
       
    65     
       
    66     iApaSession.Close();
       
    67     }
       
    68 
       
    69 void CMFPreviewHandlerBase::SetAttrL( const TDesC& aFileName )
       
    70     {
       
    71     if ( aFileName.Length() )
       
    72         {        
       
    73         delete iFullName;
       
    74         iFullName = 0;
       
    75         iFullName = aFileName.AllocL();      
       
    76         }
       
    77     }
       
    78 
       
    79 TInt CMFPreviewHandlerBase::RingingVolume()
       
    80     {
       
    81     const TInt KDefaultVolumeLevel = 7; // see profile.hrh for volume levels
       
    82     
       
    83     if ( iRingingVolume != KErrNotFound )
       
    84         {
       
    85         return iRingingVolume;
       
    86         }
       
    87         
       
    88     if ( iActiveProfileRead )
       
    89         {
       
    90         return iActiveProfileRingingVolume;
       
    91         }
       
    92 
       
    93     return KDefaultVolumeLevel;
       
    94     }
       
    95 
       
    96 TInt CMFPreviewHandlerBase::RingingType()
       
    97     {
       
    98     if ( iRingingType != KErrNotFound )
       
    99         {
       
   100         return iRingingType;
       
   101         }
       
   102         
       
   103     if ( iActiveProfileRead )
       
   104         {
       
   105         return iActiveProfileRingingType;
       
   106         }
       
   107 
       
   108     return ERingingTypeRinging;
       
   109     }
       
   110 
       
   111 TInt CMFPreviewHandlerBase::Vibra()
       
   112     {
       
   113     if ( iVibra != KErrNotFound )
       
   114         {
       
   115         return iVibra;
       
   116         }
       
   117         
       
   118     if ( iActiveProfileRead )
       
   119         {
       
   120         return iActiveProfileVibra;
       
   121         }
       
   122     
       
   123     return 0;  // in case of error vibra is off
       
   124     }
       
   125 
       
   126 TInt CMFPreviewHandlerBase::Echo3D()
       
   127     {
       
   128     if ( i3DEcho != KErrNotFound )
       
   129         {
       
   130         return i3DEcho;
       
   131         }
       
   132     
       
   133     if ( iActiveProfileRead )
       
   134         {
       
   135         return iActiveProfile3DEcho;
       
   136         }
       
   137 
       
   138     return EProfile3DEchoOff;  // from ProfileInternal.hrh
       
   139     }
       
   140 
       
   141 TInt CMFPreviewHandlerBase::Effect3D()
       
   142     {
       
   143     if ( i3DEffect != KErrNotFound )
       
   144         {
       
   145         return i3DEffect;
       
   146         }
       
   147     
       
   148     if ( iActiveProfileRead )
       
   149         {
       
   150         return iActiveProfile3DEffect;
       
   151         }
       
   152 
       
   153     return EProfile3DEffectOff;
       
   154     }
       
   155 
       
   156 TInt CMFPreviewHandlerBase::ConvertVolume( TInt aVolume, TInt aMaxVolume )
       
   157     {
       
   158     const TInt KMinVolumeLevel = 1;
       
   159     const TInt KMaxVolumeLevel = 10;
       
   160         
       
   161     TInt result = aMaxVolume * aVolume / KMaxVolumeLevel;
       
   162     
       
   163     // if user has selected minimum volume level set HW volume 1
       
   164     if ( aVolume == KMinVolumeLevel && result == 0 )
       
   165         {
       
   166         result = 1;
       
   167         }
       
   168 
       
   169     return result;
       
   170     }
       
   171   
       
   172 void CMFPreviewHandlerBase::ReadActiveProfileL()
       
   173     {
       
   174     iActiveProfileRead = EFalse;
       
   175     
       
   176     MProfileEngine* profileEngine = CreateProfileEngineL();
       
   177     CleanupReleasePushL( *profileEngine );
       
   178     
       
   179     MProfile* activeProfile  = profileEngine->ActiveProfileL();
       
   180     CleanupReleasePushL( *activeProfile );
       
   181         
       
   182     const MProfileTones& profileTones = activeProfile->ProfileTones();
       
   183      
       
   184     const TProfileToneSettings& toneSettings = profileTones.ToneSettings();
       
   185     iActiveProfileVibra = toneSettings.iVibratingAlert;
       
   186     iActiveProfileRingingVolume = toneSettings.iRingingVolume;
       
   187     iActiveProfileRingingType = toneSettings.iRingingType;
       
   188           
       
   189     const MProfileExtraSettings& extra = activeProfile->ProfileExtraSettings();
       
   190     const MProfile3DToneSettings& threeD = extra.Profile3DToneSettings();
       
   191     
       
   192     iActiveProfile3DEffect = threeD.Effect();
       
   193     iActiveProfile3DEcho = threeD.Echo();
       
   194    
       
   195     CleanupStack::PopAndDestroy( activeProfile ); 
       
   196     CleanupStack::PopAndDestroy( profileEngine );
       
   197     
       
   198     iActiveProfileRead = ETrue;
       
   199     }
       
   200  
       
   201 void CMFPreviewHandlerBase::ReadDefaultToneL()
       
   202     {
       
   203     CRepository* cenrep = CRepository::NewLC( KCRUidProfileEngine );
       
   204 
       
   205     User::LeaveIfError( cenrep->Get( KProEngDefaultRingingTone, iDefaultTone ) );
       
   206     CleanupStack::PopAndDestroy( cenrep );
       
   207     }
       
   208 
       
   209 TInt CMFPreviewHandlerBase::GetDataType( const TDesC& aFileName, TDataType& aDataType )
       
   210     {
       
   211     TUid dummyUid( KNullUid );
       
   212     return iApaSession.AppForDocument( aFileName, dummyUid, aDataType );
       
   213     }
       
   214 
       
   215 TInt CMFPreviewHandlerBase::DoResetInactivityTimer( TAny* /*aObject*/ )
       
   216     {
       
   217     User::ResetInactivityTime();
       
   218     return KErrNone;
       
   219     }
       
   220 
       
   221 void CMFPreviewHandlerBase::DisableBackLight()
       
   222     {
       
   223         const TInt KResetInactivityTimerDelay = 2000000;
       
   224     iBacklightTimer->Cancel(); // Just in case
       
   225     // Disable backlight turn off during video preview
       
   226     iBacklightTimer->Start( KResetInactivityTimerDelay,
       
   227                             KResetInactivityTimerDelay,
       
   228                             TCallBack( DoResetInactivityTimer, 0 ) );
       
   229     
       
   230     }
       
   231 
       
   232 CTonePlayer* CTonePlayer::NewL( MTonePlayingWatcher *aWatcher )
       
   233     {
       
   234     CTonePlayer* self = CTonePlayer::NewLC( aWatcher );
       
   235     CleanupStack::Pop();
       
   236     return self;
       
   237     }
       
   238 
       
   239 CTonePlayer* CTonePlayer::NewLC( MTonePlayingWatcher *aWatcher )
       
   240     {
       
   241     CTonePlayer* self = new ( ELeave ) CTonePlayer( aWatcher );
       
   242     CleanupStack::PushL( self );
       
   243     self->ConstructL();
       
   244     return self;
       
   245     }
       
   246 
       
   247 void CTonePlayer::ConstructL()
       
   248     {
       
   249     iAudioPlayerStatus = EPlayerNotCreated;
       
   250     CMFPreviewHandlerBase::ConstructL();
       
   251     iTonePlayerStatus = EPlayerNotCreated;
       
   252     CCoeEnv* coeEnv = CCoeEnv::Static();
       
   253     coeEnv->AddForegroundObserverL( *this );
       
   254     }
       
   255 
       
   256 CTonePlayer::CTonePlayer( MTonePlayingWatcher *aWatcher ) : iTonePlayWatcher( aWatcher )
       
   257     {    
       
   258     }
       
   259 
       
   260 CTonePlayer::~CTonePlayer()
       
   261     {
       
   262     Cancel();
       
   263     
       
   264     delete iAudioPlayer;
       
   265     delete iTonePlayer;
       
   266     delete i3dRingingTonePlugin;
       
   267     }
       
   268 
       
   269 TBool CTonePlayer::IsPlaying()
       
   270     {
       
   271     if ( iAudioPlayerStatus != EPlayerNotCreated )
       
   272         {
       
   273         return ETrue;
       
   274         }
       
   275     
       
   276     if ( iTonePlayerStatus != EPlayerNotCreated )
       
   277         {
       
   278         return ETrue;
       
   279         }
       
   280 
       
   281     return EFalse;
       
   282     }
       
   283 
       
   284 void CTonePlayer::PlayL()
       
   285     {    
       
   286     //sequence for playing a beep once sound
       
   287     _LIT8( KFileListBeepSequence, "\x00\x11\x06\x0A\x08\x73\x0A\x40\x28\x0A\xF7\
       
   288     \x05\xFC\x40\x64\x0A\x08\x40\x32\x0A\xF7\x06\x0B" ); 
       
   289 
       
   290     // rng mime type
       
   291     _LIT( KFileListRngMimeType, "application/vnd.nokia.ringing-tone" );
       
   292     
       
   293     Cancel(); // stop previous play
       
   294     
       
   295     if ( !iFullName || iFullName->Des().Length() == 0 )
       
   296         {
       
   297         User::Leave( KErrNotFound );
       
   298         }
       
   299 
       
   300     TRAP_IGNORE( ReadActiveProfileL() );
       
   301 
       
   302     TPtrC fileName( iFullName->Des() );
       
   303     TDataType dataType;
       
   304     TInt err = GetDataType( fileName, dataType );
       
   305     if ( err == KErrNotFound )
       
   306         {
       
   307         fileName.Set( iDefaultTone );
       
   308         if ( fileName.Length() == 0 )
       
   309              {
       
   310              User::Leave( KErrNotFound );
       
   311              }
       
   312         }
       
   313     else if ( err != KErrNone )
       
   314         {
       
   315         User::Leave( err );
       
   316         }
       
   317         
       
   318     TBool mimeTypeRng = EFalse;
       
   319     
       
   320     if ( err == KErrNone )
       
   321         {
       
   322         if( dataType.Des().CompareF( KFileListRngMimeType ) == 0 )
       
   323             {
       
   324             mimeTypeRng = ETrue;
       
   325             }
       
   326         }
       
   327 
       
   328     TInt ringingType = RingingType();
       
   329     if ( ringingType == ERingingTypeBeepOnce )
       
   330         {
       
   331         // Active profile ringing tone is set to Beep Once
       
   332         // Don't initialize a FileSequence but use DesSequence instead
       
   333         iTonePlayer = CMdaAudioToneUtility::NewL( *this );
       
   334         iTonePlayer->PrepareToPlayDesSequence( KFileListBeepSequence() );
       
   335         iTonePlayerStatus = EPlayerInitializing;
       
   336         }
       
   337     else
       
   338         {
       
   339         if( mimeTypeRng )
       
   340             {
       
   341             //Ringingtone is a RNG-file
       
   342             iTonePlayer = CMdaAudioToneUtility::NewL( *this );
       
   343             iTonePlayer->PrepareToPlayFileSequence( fileName );
       
   344             iTonePlayerStatus = EPlayerInitializing;
       
   345             }
       
   346         else
       
   347             {
       
   348             delete iAudioPlayer;
       
   349             iAudioPlayer = 0;
       
   350 
       
   351             iAudioPlayer = CDrmPlayerUtility::NewFilePlayerL(
       
   352                 fileName, *this, KAudioPriorityRingingTonePreview,
       
   353                 ( TMdaPriorityPreference )KAudioPrefRingFilePreview );
       
   354     
       
   355             iAudioPlayerStatus = EPlayerInitializing;
       
   356             }
       
   357         }
       
   358     DisableBackLight();
       
   359     }
       
   360 
       
   361 void CTonePlayer::Stop()
       
   362     {
       
   363     Cancel();
       
   364     }
       
   365 
       
   366 TInt CTonePlayer::ConvertVolume( TInt aVolume )
       
   367     {
       
   368     TInt result = 0;
       
   369     if ( iAudioPlayer )
       
   370         {
       
   371         result = CMFPreviewHandlerBase::ConvertVolume( aVolume, iAudioPlayer->MaxVolume() );
       
   372         }
       
   373     else if ( iTonePlayer )
       
   374         {
       
   375         result = CMFPreviewHandlerBase::ConvertVolume( aVolume, iTonePlayer->MaxVolume() );
       
   376         }
       
   377         
       
   378     //if user has selected silent ringing type, set volume off
       
   379     TInt ringingType = RingingType();
       
   380     if( ringingType == ERingingTypeSilent )
       
   381         {
       
   382         result = 0;
       
   383         }
       
   384 
       
   385     return result;
       
   386     }
       
   387 
       
   388 void CTonePlayer::SetToneRingingType( TInt aRingingType )
       
   389     {
       
   390     const TInt KToneInterval = 1000000; // 1 second pause between tones
       
   391     const TInt KAscendingVolumeInterval = 3000000; // 3 seconds
       
   392     
       
   393     if ( !iTonePlayer )
       
   394         {
       
   395         return;
       
   396         }
       
   397     TInt ringingVolume = RingingVolume();
       
   398     
       
   399     switch( aRingingType )
       
   400         {
       
   401         case ERingingTypeRinging:
       
   402         case ERingingTypeSilent:
       
   403             {
       
   404             iTonePlayer->SetRepeats( KMdaAudioToneRepeatForever,
       
   405                                      TTimeIntervalMicroSeconds( KToneInterval ) );
       
   406             break;
       
   407             }
       
   408         case ERingingTypeAscending:
       
   409             {
       
   410             iTonePlayer->SetRepeats( KMdaAudioToneRepeatForever,
       
   411                                      TTimeIntervalMicroSeconds( KToneInterval ) );
       
   412             
       
   413             TInt volRamp = KAscendingVolumeInterval * ringingVolume;
       
   414             iTonePlayer->SetVolumeRamp( TTimeIntervalMicroSeconds( volRamp ) );
       
   415             break;
       
   416             }
       
   417         case ERingingTypeRingOnce:
       
   418         case ERingingTypeBeepOnce:
       
   419             {
       
   420             iTonePlayer->SetRepeats( 0, TTimeIntervalMicroSeconds( KToneInterval ) );
       
   421             break;
       
   422             }
       
   423         default:
       
   424             {
       
   425             break;
       
   426             }
       
   427         }
       
   428     }
       
   429 
       
   430 void CTonePlayer::SetAudioRingingType( TInt aRingingType )
       
   431     {
       
   432     const TInt KToneInterval = 1000000; // 1 second pause between tones
       
   433     const TInt KAscendingVolumeInterval = 3000000; // 3 seconds
       
   434     
       
   435     if ( !iAudioPlayer )
       
   436         {
       
   437         return;
       
   438         }
       
   439 
       
   440     TInt ringingVolume = RingingVolume();
       
   441         
       
   442     switch( aRingingType )
       
   443         {
       
   444         case ERingingTypeRinging:
       
   445         case ERingingTypeSilent:
       
   446             {
       
   447             iAudioPlayer->SetRepeats( KMdaAudioToneRepeatForever,
       
   448                                       TTimeIntervalMicroSeconds( KToneInterval ) );
       
   449             break;
       
   450             }
       
   451         case ERingingTypeAscending:
       
   452             {
       
   453             iAudioPlayer->SetRepeats( KMdaAudioToneRepeatForever,
       
   454                                       TTimeIntervalMicroSeconds( KToneInterval ) );
       
   455             TInt volRamp = KAscendingVolumeInterval * ringingVolume;
       
   456             iAudioPlayer->SetVolumeRamp( TTimeIntervalMicroSeconds( volRamp ) );
       
   457             break;
       
   458             }
       
   459         case ERingingTypeRingOnce:
       
   460             {
       
   461             iAudioPlayer->SetRepeats( 0, TTimeIntervalMicroSeconds( KToneInterval ) );
       
   462             break;
       
   463             }
       
   464 
       
   465         default:
       
   466             {
       
   467             break;
       
   468             }
       
   469         }
       
   470     }
       
   471 
       
   472 void CTonePlayer::Cancel()
       
   473     {
       
   474     TBool isPlaying = EFalse;
       
   475     
       
   476     if ( iAudioPlayer )
       
   477         {
       
   478         isPlaying = ETrue;
       
   479         if ( iAudioPlayerStatus == EPlayerPlayingWith3DEffect )
       
   480             {
       
   481             i3dRingingTonePlugin->Stop();
       
   482             // plugin calls AudioPlayer->Stop()
       
   483             iAudioPlayer->Close();
       
   484             }
       
   485         if ( iAudioPlayerStatus == EPlayerPlaying )
       
   486             {
       
   487             iAudioPlayer->Stop();
       
   488             iAudioPlayer->Close();
       
   489             }
       
   490         
       
   491         delete iAudioPlayer;
       
   492         iAudioPlayer = 0;
       
   493         iAudioPlayerStatus = EPlayerNotCreated;
       
   494         }
       
   495     
       
   496     if ( iTonePlayer )
       
   497         {
       
   498         isPlaying = ETrue;
       
   499         if ( iTonePlayerStatus == EPlayerPlaying )
       
   500             {
       
   501             iTonePlayer->CancelPlay();
       
   502             }
       
   503         
       
   504         delete iTonePlayer;
       
   505         iTonePlayer = 0;
       
   506         iTonePlayerStatus = EPlayerNotCreated;
       
   507         }
       
   508         
       
   509 
       
   510     if ( isPlaying )
       
   511         {
       
   512         //User::InfoPrint(_L("cancel"));
       
   513 //        EnableScreenSaver( ETrue );
       
   514         iBacklightTimer->Cancel();
       
   515         }
       
   516     }
       
   517 
       
   518 void CTonePlayer::MatoPlayComplete( TInt aError )
       
   519     {
       
   520     Cancel();
       
   521     iTonePlayWatcher->HandlePreviewEvent( aError );
       
   522     }
       
   523 
       
   524 void CTonePlayer::MatoPrepareComplete( TInt aError )
       
   525     {
       
   526     if ( aError != KErrNone )
       
   527         {
       
   528         Cancel();
       
   529         
       
   530         iTonePlayWatcher->HandlePreviewEvent( aError );
       
   531         return;
       
   532         }
       
   533 
       
   534     TInt ringingVolume = RingingVolume();
       
   535     TInt ringingType = RingingType();
       
   536     TInt vibra = Vibra();
       
   537        
       
   538     iTonePlayerStatus = EPlayerInitialized;
       
   539     SetToneRingingType( ringingType );
       
   540     iTonePlayer->SetVolume( ConvertVolume( ringingVolume ) );
       
   541     
       
   542     TMdaPriorityPreference pref = (TMdaPriorityPreference) KAudioPrefRingFilePreview;               
       
   543     if ( vibra )
       
   544         {
       
   545         pref = (TMdaPriorityPreference) KAudioPrefRingFilePreviewVibra;
       
   546         }
       
   547     iTonePlayer->SetPriority( KAudioPriorityPreview, pref );
       
   548                                              
       
   549     iTonePlayer->Play();
       
   550     iTonePlayerStatus = EPlayerPlaying;
       
   551     }
       
   552 
       
   553 void CTonePlayer::MdapcInitComplete( TInt aError, 
       
   554                         const TTimeIntervalMicroSeconds& /* aDuration */ )
       
   555     {
       
   556     if ( aError != KErrNone )
       
   557         {
       
   558         Cancel();
       
   559         iTonePlayWatcher->HandlePreviewEvent( aError );
       
   560         return;
       
   561         }
       
   562         
       
   563 
       
   564     TInt ringingVolume = RingingVolume();
       
   565     TInt ringingType = RingingType();
       
   566     TInt vibra = Vibra();
       
   567     TInt echo3D = Echo3D();
       
   568     TInt effect3D = Effect3D();
       
   569 
       
   570     
       
   571 
       
   572     iAudioPlayerStatus = EPlayerInitialized;
       
   573     SetAudioRingingType( ringingType );
       
   574     iAudioPlayer->SetVolume( ConvertVolume( ringingVolume ) );
       
   575     
       
   576     TMdaPriorityPreference pref = (TMdaPriorityPreference) KAudioPrefRingFilePreview;               
       
   577     if ( vibra )
       
   578         {
       
   579         pref = (TMdaPriorityPreference) KAudioPrefRingFilePreviewVibra;
       
   580         }
       
   581     iAudioPlayer->SetPriority( KAudioPriorityPreview, pref );
       
   582      
       
   583     iAudioPlayerStatus = EPlayerPlaying;
       
   584     
       
   585     if ( effect3D == EProfile3DEffectOff )
       
   586         {
       
   587         iAudioPlayer->Play();  // 3D not used
       
   588         return;
       
   589         }
       
   590 
       
   591     if ( !i3dRingingTonePlugin )
       
   592         {
       
   593         TUid emptyUid = { 0 };
       
   594         TRAPD( err, i3dRingingTonePlugin = C3DRingingToneInterface::NewL( emptyUid ) );
       
   595         if ( err != KErrNone || !i3dRingingTonePlugin )
       
   596             {
       
   597             iAudioPlayer->Play();
       
   598             return;
       
   599             }
       
   600         }       
       
   601    
       
   602     i3dRingingTonePlugin->SetAttr( E3DRTIAttr3DEffect, effect3D );
       
   603     i3dRingingTonePlugin->SetAttr( E3DRTIAttr3DEcho, echo3D );    
       
   604     i3dRingingTonePlugin->SetAttr( E3DRTIAttrDrmPlayerUtility, iAudioPlayer );
       
   605     TRAP_IGNORE( i3dRingingTonePlugin->PlayL() );
       
   606 
       
   607     iAudioPlayerStatus = EPlayerPlayingWith3DEffect;
       
   608     }
       
   609 
       
   610 void CTonePlayer::MdapcPlayComplete( TInt aError )
       
   611     {  
       
   612     Cancel();
       
   613     iTonePlayWatcher->HandlePreviewEvent( aError );
       
   614     }
       
   615 
       
   616 void CTonePlayer::HandleLosingForeground()
       
   617     {
       
   618     if ( IsPlaying() )
       
   619         {
       
   620         Stop();
       
   621         }
       
   622     }
       
   623 void CTonePlayer::HandleGainingForeground()
       
   624     {
       
   625     
       
   626     }