bluetoothengine/btsac/btrcc/src/btrccLegacyVolumeLevelController.cpp
changeset 0 f63038272f30
child 15 53b7818cd282
equal deleted inserted replaced
-1:000000000000 0:f63038272f30
       
     1 /*
       
     2 * Copyright (c) 2005-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:   This class implements legacy volume control of AVRCP Controller.	
       
    15 *
       
    16 *
       
    17 */
       
    18 
       
    19 // INCLUDE FILES
       
    20 #include <remconbeareravrcp.h> //	KRemConBearerAvrcpImplementationUid = 0x1020685f
       
    21 #include <MediaStreamPropertiesPSKeys.h>
       
    22 #include <remconinterfaceselector.h> 
       
    23 #include <remconcoreapicontroller.h> 
       
    24 #include <remconaddress.h>
       
    25 #include <e32math.h>
       
    26 
       
    27 #include "btrccLegacyVolumeLevelController.h"
       
    28 #include "debug.h"
       
    29 
       
    30 const TInt KVolumeNotSynchronized = -1;
       
    31 const TInt KLegacyVolumeLevelSetServiceId = 0x03;
       
    32 
       
    33 const TInt KVolumeSyncRecheckTimer = 500000; // 0.5 second
       
    34 const TInt KVolumeCommandInterval = 50000; // 0.05 second
       
    35 
       
    36 const TInt KVolumeScaleMax = 15;
       
    37 
       
    38 // MODULE DATA STRUCTURES
       
    39 
       
    40 // ================= MEMBER FUNCTIONS =======================
       
    41 
       
    42 // -----------------------------------------------------------------------------
       
    43 // CBTRCCLegacyVolumeLevelController::NewL
       
    44 // Two-phased constructor.
       
    45 // -----------------------------------------------------------------------------
       
    46 //
       
    47 CBTRCCLegacyVolumeLevelController* CBTRCCLegacyVolumeLevelController::NewL(CRemConInterfaceSelector& aInterfaceSelector, MBTRCCVolumeControllerObserver& aObserver)
       
    48 	{
       
    49 	CBTRCCLegacyVolumeLevelController* self = new (ELeave) CBTRCCLegacyVolumeLevelController(aObserver);
       
    50 	CleanupStack::PushL(self);
       
    51 	self->ConstructL(aInterfaceSelector);
       
    52 	CleanupStack::Pop(self);
       
    53 	return self;
       
    54 	}
       
    55 
       
    56 // -----------------------------------------------------------------------------
       
    57 // CBTRCCLegacyVolumeLevelController::CBTRCCVolumeLevelController
       
    58 // C++ constructor.
       
    59 // -----------------------------------------------------------------------------
       
    60 //
       
    61 CBTRCCLegacyVolumeLevelController::CBTRCCLegacyVolumeLevelController(MBTRCCVolumeControllerObserver& aObserver)
       
    62   : CBTRCCVolumeLevelControllerBase(aObserver), iState(EStateWaitingForVolumeLevelChanges), iPhoneVolume(KVolumeNotSynchronized),
       
    63     iCurrentPhoneVolume(KVolumeNotSynchronized), iCurrentRemoteVolume(KVolumeNotSynchronized)
       
    64 	{
       
    65 	}
       
    66 
       
    67 // -----------------------------------------------------------------------------
       
    68 // CBTRCCLegacyVolumeLevelController::ConstructL
       
    69 // Symbian 2nd phase constructor.
       
    70 // -----------------------------------------------------------------------------
       
    71 //
       
    72 void CBTRCCLegacyVolumeLevelController::ConstructL(CRemConInterfaceSelector& aInterfaceSelector)
       
    73 	{
       
    74    	TRACE_FUNC
       
    75    	CBTRCCVolumeLevelControllerBase::ConstructL();
       
    76     iInterfaceSelector = &aInterfaceSelector;
       
    77    	iRemConVolController = CRemConCoreApiController::NewL(aInterfaceSelector, *this); 
       
    78     TRACE_INFO((_L("CRemConCoreApiController created")))
       
    79     iBtrccLegacyVolumeActive = CBTRCCActive::NewL(*this, KLegacyVolumeLevelSetServiceId);
       
    80     TRACE_INFO((_L("CBTRCCActive created")))
       
    81     iCtrlRTimer.CreateLocal();    
       
    82     TRACE_INFO((_L("RTimer created")))
       
    83     iLocalMaxVolume = GetLocalMaxVolume();
       
    84 	}
       
    85 
       
    86 // -----------------------------------------------------------------------------
       
    87 // Destructor.
       
    88 // -----------------------------------------------------------------------------
       
    89 //
       
    90 CBTRCCLegacyVolumeLevelController::~CBTRCCLegacyVolumeLevelController()
       
    91 	{
       
    92 	TRACE_FUNC
       
    93     delete iBtrccLegacyVolumeActive;
       
    94 	iCtrlRTimer.Close();
       
    95 	}
       
    96 
       
    97 // -----------------------------------------------------------------------------
       
    98 // CBTRCCLegacyVolumeLevelController::DoStart
       
    99 // -----------------------------------------------------------------------------
       
   100 //
       
   101 void CBTRCCLegacyVolumeLevelController::DoStart(TInt aInitialVolume) 
       
   102     {
       
   103     TRACE_FUNC   	
       
   104     AdjustRemoteVolume(aInitialVolume);
       
   105     }
       
   106 
       
   107 // -----------------------------------------------------------------------------
       
   108 // CBTRCCLegacyVolumeLevelController::DoStop
       
   109 // -----------------------------------------------------------------------------
       
   110 //
       
   111 void CBTRCCLegacyVolumeLevelController::DoStop() 
       
   112     {
       
   113     TRACE_FUNC
       
   114     iBtrccLegacyVolumeActive->Cancel();
       
   115     iState = EStateWaitingForVolumeLevelChanges;
       
   116     }
       
   117 
       
   118 // -----------------------------------------------------------------------------
       
   119 // CBTRCCLegacyVolumeLevelController::DoReset
       
   120 // -----------------------------------------------------------------------------
       
   121 //
       
   122 void CBTRCCLegacyVolumeLevelController::DoReset()
       
   123     {
       
   124     TRACE_FUNC
       
   125     iBtrccLegacyVolumeActive->Cancel();
       
   126    	iCurrentRemoteVolume = KVolumeNotSynchronized;
       
   127     }
       
   128 
       
   129 // -----------------------------------------------------------------------------
       
   130 // CBTRCCLegacyVolumeLevelController::AdjustRemoteVolume
       
   131 // -----------------------------------------------------------------------------
       
   132 //
       
   133 void CBTRCCLegacyVolumeLevelController::AdjustRemoteVolume(TInt aVolume)
       
   134     {
       
   135     // A call to this is made when PS Key changes. 
       
   136     TRACE_INFO((_L("CBTRCCLegacyVolumeLevelController::AdjustRemoteVolume, volume %d, state %d"), aVolume, iState))    
       
   137     iPhoneVolume = aVolume;
       
   138     
       
   139     if(iCurrentRemoteVolume == KVolumeNotSynchronized)
       
   140         {
       
   141         // We set current phone volume level as the reference synchronization point
       
   142         // if we haven't done it yet. Otherwise we synchronize remote to the current level.
       
   143         // Just synchronize volumes and return, there is nothing else to do at this point.
       
   144         iCurrentRemoteVolume = iPhoneVolume;
       
   145         return;
       
   146         }
       
   147     
       
   148     switch(iState)
       
   149         {
       
   150         case EStateWaitingForVolumeLevelChanges:
       
   151             // Just break here.
       
   152             break;
       
   153         case EStateDelay:
       
   154             // Sharp volume jump handling is ongoing. In this case we want to update
       
   155             // new volume level immediately.
       
   156             if( iBtrccLegacyVolumeActive->IsActive() )
       
   157                 {
       
   158                 iBtrccLegacyVolumeActive->Cancel();
       
   159                 }
       
   160             break;
       
   161         default:
       
   162             // We are middle of timing or volume up/down processing. New value
       
   163             // is stored, just return here. New value is updated after previous
       
   164             // job is done.
       
   165             return;
       
   166         }
       
   167     
       
   168     DoRemoteControl();
       
   169     }
       
   170 
       
   171 // -----------------------------------------------------------------------------
       
   172 // CBTRCCLegacyVolumeLevelController::DoRemoteControl
       
   173 // -----------------------------------------------------------------------------
       
   174 //
       
   175 void CBTRCCLegacyVolumeLevelController::DoRemoteControl()
       
   176     {
       
   177     TRACE_INFO((_L("target volume level %d"), iPhoneVolume))
       
   178     TRACE_INFO((_L("phone current volume level %d"), iCurrentPhoneVolume))
       
   179 	TRACE_INFO((_L("remote current volume level %d"), iCurrentRemoteVolume))
       
   180 	
       
   181 	TState preState = iState;
       
   182 	iState = EStateWaitingForVolumeLevelChanges;
       
   183 	
       
   184 	if ( iPhoneVolume != iCurrentRemoteVolume )
       
   185 	    {
       
   186 	    TInt prevPhoneVolume = iCurrentPhoneVolume;
       
   187 	    iCurrentPhoneVolume = iPhoneVolume;
       
   188 
       
   189         if ( iCurrentPhoneVolume == 0 && prevPhoneVolume > 1 )
       
   190             {
       
   191             // A sharp volume jump, most probably caused by audio stream switching.
       
   192             // Delay the starting of audio adjustment for 0.5 seconds.
       
   193             iState = EStateDelay;
       
   194             }
       
   195 	    else if (iCurrentPhoneVolume > iCurrentRemoteVolume)
       
   196 	        {
       
   197 	        iState = preState == EStateVolumeUpTiming ? EStateVolumeUp : EStateVolumeUpTiming;  
       
   198 	        }
       
   199     	else if (iCurrentPhoneVolume < iCurrentRemoteVolume)
       
   200     	    {
       
   201 	        iState = preState == EStateVolumeDownTiming ? EStateVolumeDown : EStateVolumeDownTiming; 
       
   202     	    }
       
   203 	    }
       
   204 	
       
   205     switch (iState)
       
   206         {
       
   207         case EStateVolumeUpTiming:
       
   208         	{
       
   209         	TRACE_INFO(_L("Volume up timing"))
       
   210         	StartTimer(KVolumeCommandInterval);
       
   211         	break;	
       
   212         	}        
       
   213         case EStateVolumeUp:
       
   214             {
       
   215 			TRACE_INFO(_L("Volume up"))
       
   216 			SendVolumeCommand(EStateVolumeUp); 
       
   217             break;
       
   218             }
       
   219         case EStateVolumeDownTiming:
       
   220         	{
       
   221         	TRACE_INFO(_L("Volume down timing"))
       
   222         	StartTimer(KVolumeCommandInterval);
       
   223         	break;	
       
   224         	}            
       
   225         case EStateVolumeDown:
       
   226             {
       
   227 			TRACE_INFO(_L("Volume down"))
       
   228 			SendVolumeCommand(EStateVolumeDown); 
       
   229             break;
       
   230             }
       
   231         case EStateDelay:
       
   232             {
       
   233             TRACE_INFO(_L("Delay before updating volume"))
       
   234             StartTimer( KVolumeSyncRecheckTimer );
       
   235             break;
       
   236             }
       
   237         case EStateWaitingForVolumeLevelChanges:
       
   238             {
       
   239 			TRACE_INFO(_L("Waiting volume change"))
       
   240             break;
       
   241             }
       
   242         default:
       
   243             {
       
   244             // Not possible
       
   245             }
       
   246         }
       
   247     }
       
   248 
       
   249 // -----------------------------------------------------------------------------
       
   250 // CBTRCCLegacyVolumeLevelController::GetPhoneVolume
       
   251 // -----------------------------------------------------------------------------
       
   252 //
       
   253 TInt CBTRCCLegacyVolumeLevelController::GetPhoneVolume(TInt &aVol)
       
   254     {
       
   255     TRACE_FUNC
       
   256     TInt err = CBTRCCVolumeLevelControllerBase::GetPhoneVolume(aVol); 
       
   257         
       
   258     // Converts volume level scale used in DevSound Audio (0 - 10000) into 0 - KVolumeScaleMax.
       
   259     if( aVol <= 0 )
       
   260         {
       
   261         // 0 level and -1 (no stream) don't need adjustment. 
       
   262         return err;
       
   263         }
       
   264     
       
   265     TReal tgt;
       
   266     TReal src(aVol);    
       
   267     TReal maxScale(KVolumeScaleMax);    
       
   268     TReal maxDevSound(iLocalMaxVolume);
       
   269     TReal scale = maxScale/maxDevSound;
       
   270     Math::Round( tgt, src*scale, 0);
       
   271     
       
   272     if( TInt(tgt) == 0 )
       
   273         {
       
   274         // Only aVol value 0 is real zero (muted). All other scaled zero
       
   275         // values have to be upgraded to level 1.
       
   276         tgt = 1;
       
   277         }
       
   278     TRACE_INFO((_L("Volume scaled: original %d, scaled %d"), aVol, TInt(tgt)))
       
   279     aVol = TInt(tgt);
       
   280     return err;
       
   281     }
       
   282 
       
   283 // -----------------------------------------------------------------------------
       
   284 // CBTRCCLegacyVolumeLevelController::RequestCompletedL
       
   285 // -----------------------------------------------------------------------------
       
   286 //
       
   287 void CBTRCCLegacyVolumeLevelController::RequestCompletedL(CBTRCCActive& aActive, TInt aErr)
       
   288     {
       
   289     TRACE_FUNC 
       
   290     if( aActive.ServiceId() == KLegacyVolumeLevelSetServiceId )
       
   291         {
       
   292         TRACE_INFO( (_L("CBTRCCLegacyVolumeLevelController iState: %d"), iState ) )
       
   293         if ( aErr != KErrNone )
       
   294             {
       
   295             // Something wrong happened, could be e.g. the connection has
       
   296             // been released while we are changing volume on remote device.
       
   297             iState = EStateWaitingForVolumeLevelChanges;
       
   298             return;
       
   299             }
       
   300         switch(iState)
       
   301             {
       
   302             case EStateVolumeUp:
       
   303                 {
       
   304                 ++iCurrentRemoteVolume;
       
   305                 break;
       
   306                 }
       
   307             case EStateVolumeDown:
       
   308                 {
       
   309                 --iCurrentRemoteVolume;
       
   310                 break;
       
   311                 }
       
   312             case EStateDelay:
       
   313             case EStateWaitingForVolumeLevelChanges:
       
   314             case EStateVolumeUpTiming:
       
   315             case EStateVolumeDownTiming:
       
   316                 break;
       
   317             default:
       
   318                 // Impossible to happen.
       
   319                 break;
       
   320             }
       
   321         DoRemoteControl();
       
   322         }
       
   323     else 
       
   324         {
       
   325         // This is something the base class can handle. 
       
   326         CBTRCCVolumeLevelControllerBase::RequestCompletedL(aActive, aErr);
       
   327         }
       
   328     }
       
   329 
       
   330 // -----------------------------------------------------------------------------
       
   331 // CBTRCCLegacyVolumeLevelController::CancelRequest
       
   332 // -----------------------------------------------------------------------------
       
   333 //
       
   334 void CBTRCCLegacyVolumeLevelController::CancelRequest(TInt aServiceId) 
       
   335     {
       
   336     TRACE_FUNC 
       
   337     if( aServiceId == KLegacyVolumeLevelSetServiceId )
       
   338         {
       
   339         // Cancel possible active timers
       
   340         iCtrlRTimer.Cancel();
       
   341 
       
   342         if (iState == EStateVolumeUp)
       
   343             {
       
   344             ++iCurrentRemoteVolume;
       
   345             }
       
   346         else if (iState == EStateVolumeDown)
       
   347             {
       
   348             --iCurrentRemoteVolume;
       
   349             }
       
   350         }
       
   351     else
       
   352         {
       
   353         // This is something the base class can handle.
       
   354         CBTRCCVolumeLevelControllerBase::CancelRequest(aServiceId);
       
   355         }
       
   356     }
       
   357 
       
   358 // -----------------------------------------------------------------------------
       
   359 // CBTRCCLegacyVolumeLevelController::StartTimer
       
   360 // -----------------------------------------------------------------------------
       
   361 //
       
   362 void CBTRCCLegacyVolumeLevelController::StartTimer(TInt aInterval) 
       
   363     {
       
   364     TRACE_FUNC 
       
   365     if( !iBtrccLegacyVolumeActive->IsActive() )
       
   366         {
       
   367         iCtrlRTimer.After(iBtrccLegacyVolumeActive->iStatus, aInterval);
       
   368         iBtrccLegacyVolumeActive->GoActive();
       
   369         }
       
   370     else
       
   371         {
       
   372         TRACE_INFO(_L("CBTRCCLegacyVolumeLevelController::StartTimer() ERR, timer already active!"))
       
   373         }
       
   374     }
       
   375 
       
   376 // -----------------------------------------------------------------------------
       
   377 // CBTRCCLegacyVolumeLevelController::SendVolumeCommand
       
   378 // -----------------------------------------------------------------------------
       
   379 //
       
   380 void CBTRCCLegacyVolumeLevelController::SendVolumeCommand(TInt aDirection) 
       
   381     {
       
   382     TRACE_FUNC 
       
   383     if( !iBtrccLegacyVolumeActive->IsActive() )
       
   384         {
       
   385         if( aDirection == EStateVolumeUp )
       
   386             {
       
   387             iRemConVolController->VolumeUp(iBtrccLegacyVolumeActive->iStatus, iNumRemotes, ERemConCoreApiButtonClick);
       
   388             }
       
   389         else
       
   390             {
       
   391             iRemConVolController->VolumeDown(iBtrccLegacyVolumeActive->iStatus, iNumRemotes, ERemConCoreApiButtonClick);
       
   392             }
       
   393         iBtrccLegacyVolumeActive->GoActive();
       
   394         }
       
   395     else
       
   396         {
       
   397         TRACE_INFO(_L("CBTRCCLegacyVolumeLevelController::DoRemConControl() ERR, previous action ongoing!"))
       
   398         }
       
   399     }
       
   400 
       
   401 // -----------------------------------------------------------------------------
       
   402 // CBTRCCLegacyVolumeLevelController::MrccacoResponse()
       
   403 // -----------------------------------------------------------------------------
       
   404 //
       
   405 TInt CBTRCCLegacyVolumeLevelController::MrccacoResponse()
       
   406 	{
       
   407 	TRACE_FUNC
       
   408 	return 0; 
       
   409     }
       
   410 
       
   411 //  End of File