bluetoothappprofiles/avrcp/absolutevolumeapi/src/absolutevolumeapicontroller.cpp
changeset 70 f5508c13dfe0
parent 67 16e4b9007960
child 71 083fd884d7dd
equal deleted inserted replaced
67:16e4b9007960 70:f5508c13dfe0
     1 // Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 
       
    17 
       
    18 /**
       
    19  @file
       
    20  @publishedAll
       
    21  @released
       
    22 */
       
    23 
       
    24 #include <e32def.h>
       
    25 #include <absolutevolumeapicontroller.h>
       
    26 #include <absolutevolumeapicontrollerobserver.h>
       
    27 #include <remconinterfaceselector.h>
       
    28 #include "absolutevolumesender.h"
       
    29 #include <absolutevolumeutils.h>
       
    30 #include <bluetooth/logger.h>
       
    31 
       
    32 #ifdef __FLOG_ACTIVE
       
    33 _LIT8(KLogComponent, LOG_COMPONENT_REMCONABSOLUTEVOLUME);
       
    34 #endif
       
    35 
       
    36 #ifdef _DEBUG
       
    37 _LIT(KAbsoluteVolumeControllerFaultName, "AbsVolFault");
       
    38 // The panic codes associated with category KAbsoluteVolumeControllerFaultName are line numbers in this file.
       
    39 #endif
       
    40 
       
    41 /**
       
    42 Allocates and constructs a new CRemConAbsoluteVolumeController object
       
    43 
       
    44 @param aInterfaceSelector The interface selector. The client must have 
       
    45        created one of these first.
       
    46 @param aObserver The observer. The client must have implemented the observer,
       
    47        owned by the client.
       
    48 @param aMaxVolume The client maximum volume.
       
    49 @return A new CRemConAbsoluteVolumeController, owned by the interface selector
       
    50 @panic AbsoluteVolumeController 0 if aMaxVolume is zero.
       
    51 */
       
    52 EXPORT_C 
       
    53 CRemConAbsoluteVolumeController* CRemConAbsoluteVolumeController::NewL(
       
    54 		CRemConInterfaceSelector& aInterfaceSelector, 
       
    55 		MRemConAbsoluteVolumeControllerObserver& aObserver,
       
    56 		TUint32 aMaxVolume)
       
    57 	{
       
    58 	LOG_STATIC_FUNC
       
    59 	
       
    60 	__ASSERT_ALWAYS(aMaxVolume > 0, 
       
    61 				User::Panic(KAbsoluteVolumeControllerPanicName, 
       
    62 						EControllerInvalidMaxVolume)
       
    63 				);
       
    64 				
       
    65 	CRemConAbsoluteVolumeController* self = 
       
    66 	new(ELeave) CRemConAbsoluteVolumeController(aInterfaceSelector, 
       
    67 			aObserver, aMaxVolume);
       
    68 	
       
    69 	CleanupStack::PushL(self);
       
    70 	self->ConstructL();
       
    71 	CleanupStack::Pop(self);
       
    72 	return self;
       
    73 	}
       
    74 
       
    75 /** 
       
    76 Constructor.
       
    77 
       
    78 @param aInterfaceSelector The interface selector.
       
    79 @param aObserver The observer.
       
    80 */
       
    81 CRemConAbsoluteVolumeController::CRemConAbsoluteVolumeController(
       
    82 		CRemConInterfaceSelector& aInterfaceSelector, 
       
    83 		MRemConAbsoluteVolumeControllerObserver& aObserver,
       
    84 		TUint32 aMaxVolume)
       
    85 :	CRemConInterfaceBase(TUid::Uid(KRemConAbsoluteVolumeControllerApiUid), 
       
    86 		KAbsoluteVolumeResponseDataSize,
       
    87 		aInterfaceSelector,
       
    88 		ERemConClientTypeController),
       
    89     iObserver(aObserver),
       
    90     iClientMaxVolume(aMaxVolume),
       
    91 	iNotificationRequested(EFalse),
       
    92 	iAbsVolRequest(ENotInUse),
       
    93 	iNotifyRequest(ENotInUse)
       
    94 	{
       
    95 	LOG_FUNC
       
    96 	}
       
    97 
       
    98 EXPORT_C CRemConAbsoluteVolumeController::~CRemConAbsoluteVolumeController()
       
    99     {
       
   100 	LOG_FUNC
       
   101 	LOG2(_L8("\tiAbsVolRequest = %d, iNotifyRequest = %d"), iAbsVolRequest, iNotifyRequest);
       
   102 	
       
   103 	delete iAbsVolSender;
       
   104     }
       
   105 
       
   106 void CRemConAbsoluteVolumeController::ConstructL()
       
   107 	{
       
   108 	LOG_FUNC
       
   109 	
       
   110 	iAbsVolSender = CAbsVolSender::NewL(InterfaceSelector(), *this);
       
   111 	BaseConstructL();
       
   112 	}
       
   113 
       
   114 /**
       
   115 Sets an absolute volume on the target device,
       
   116 Any responses will be returned via the observer interface.
       
   117 
       
   118 @pre The send of any previous SetAbsoluteVolume command has completed.
       
   119 @param aStatus Indicates the completion of the send request.  The client must
       
   120 			   not block execution by using User::WaitForRequest to await 
       
   121 			   completion of this send.
       
   122 @param aVolume The relative volume against the client max volume.
       
   123 @param aNumRemotes The number of remotes to which the command was sent.
       
   124 @panic AbsoluteVolumeController 1, if aVolume greater than the client 
       
   125        max volume.
       
   126 */
       
   127 EXPORT_C void CRemConAbsoluteVolumeController::SetAbsoluteVolume(
       
   128 		TRequestStatus& aStatus, 
       
   129 		TUint32 aVolume, 
       
   130 		TUint& aNumRemotes)
       
   131 	{
       
   132 	LOG_FUNC
       
   133 	LOG1(_L8("\taVolume = %d"), aVolume);
       
   134 	LOG2(_L8("\tiAbsVolRequest = %d, iNotifyRequest = %d"), iAbsVolRequest, iNotifyRequest);
       
   135 	
       
   136 	__ASSERT_ALWAYS(aVolume <= iClientMaxVolume, 
       
   137 			User::Panic(KAbsoluteVolumeControllerPanicName, 
       
   138 					EControllerVolumeBeyondMaxVolume)
       
   139 			);
       
   140 	__ASSERT_DEBUG(iAbsVolRequest == ENotInUse, User::Panic(KAbsoluteVolumeControllerPanicName, 
       
   141 				EMultipleSetAbsoluteVolumes));
       
   142 	
       
   143 	RRemConAbsoluteVolumeRequest setAbsVol;
       
   144 	setAbsVol.iVolume = aVolume;
       
   145 	setAbsVol.iMaxVolume = iClientMaxVolume;
       
   146 	TRAPD(err, setAbsVol.WriteL(iSetData));
       
   147 	if (err == KErrNone)
       
   148 		{
       
   149 		// Store the client's info so we can complete their request later
       
   150 		aStatus = KRequestPending;
       
   151 		iAbsVolRequest = EPending;
       
   152 		__ASSERT_DEBUG(iClientStatus == NULL, User::Panic(KAbsoluteVolumeControllerFaultName, __LINE__));
       
   153 		iClientStatus = &aStatus;
       
   154 		__ASSERT_DEBUG(iClientNumRemotes == NULL, User::Panic(KAbsoluteVolumeControllerFaultName, __LINE__));
       
   155 		iClientNumRemotes = &aNumRemotes;
       
   156 		KickOffSendIfNeeded();
       
   157 		}
       
   158 	else
       
   159 		{
       
   160 		iObserver.MrcavcoSetAbsoluteVolumeResponse(0, 0, err);
       
   161 		}
       
   162 	}
       
   163 
       
   164 EXPORT_C void CRemConAbsoluteVolumeController::CancelSetAbsoluteVolume()
       
   165 	{
       
   166 	LOG_FUNC
       
   167 	LOG2(_L8("\tiAbsVolRequest = %d, iNotifyRequest = %d"), iAbsVolRequest, iNotifyRequest);
       
   168 	
       
   169 	switch ( iAbsVolRequest )
       
   170 		{
       
   171 	case ENotInUse:
       
   172 		// Nothing to do.
       
   173 		break;
       
   174 	case ESending:
       
   175 		iAbsVolSender->Cancel();
       
   176 		SetAbsoluteVolumeSendComplete(KErrCancel);
       
   177 		break;
       
   178 	case EPending:
       
   179 		SetAbsoluteVolumeSendComplete(KErrCancel);
       
   180 		break;
       
   181 	default:
       
   182 		__ASSERT_DEBUG(EFalse, User::Panic(KAbsoluteVolumeControllerFaultName, __LINE__));
       
   183 		break;
       
   184 		}
       
   185 	}
       
   186 
       
   187 /**
       
   188 Requests notification when the volume on the target device changes,
       
   189 Any responses will be returned via the observer interface.
       
   190 
       
   191 Volume changes will continue to be provided until either the 
       
   192 CancelAbsoluteVolumeNotification function is called, or MrcavcoCurrentVolume
       
   193 is called on the client with an error.
       
   194 
       
   195 @see MRemConAbsoluteVolumeControllerObserver::MrcavcoCurrentVolume
       
   196 @see CRemConAbsoluteVolumeController::CancelAbsoluteVolumeNotification
       
   197 @pre The client is not currently registered to receive absolute volume notifications.
       
   198 */
       
   199 EXPORT_C 
       
   200 void CRemConAbsoluteVolumeController::RegisterAbsoluteVolumeNotification()
       
   201 	{
       
   202 	LOG_FUNC
       
   203 	LOG2(_L8("\tiAbsVolRequest = %d, iNotifyRequest = %d"), iAbsVolRequest, iNotifyRequest);
       
   204 	
       
   205 	// The request is outstanding, so not allowed to register again.
       
   206 	__ASSERT_DEBUG(!iNotificationRequested, User::Panic(KAbsoluteVolumeControllerPanicName, EAbsoluteVolumeNotificationAlreadyRegistered));
       
   207 	__ASSERT_DEBUG(iNotifyRequest == ENotInUse, User::Panic(KAbsoluteVolumeControllerPanicName, EMultipleNotifies));
       
   208 	
       
   209 	RRemConAbsoluteVolumeRequest absVol;
       
   210 	TRAPD(err, absVol.WriteL(iNotifyData));
       
   211 	if (err == KErrNone)
       
   212 		{
       
   213 		iNotifyRequest = EPending;
       
   214 		iNotificationRequested = ETrue;
       
   215 		KickOffSendIfNeeded();
       
   216 		}
       
   217 	else
       
   218 		{
       
   219 		iObserver.MrcavcoAbsoluteVolumeNotificationError();
       
   220 		}
       
   221 	}
       
   222 
       
   223 /**
       
   224 Called by the client to tell the controller that the client doesn't wish to 
       
   225 receicve the volume change notification
       
   226 until the client re-register again.
       
   227 */
       
   228 EXPORT_C 
       
   229 void CRemConAbsoluteVolumeController::CancelAbsoluteVolumeNotification()
       
   230 	{
       
   231 	LOG_FUNC
       
   232 	LOG2(_L8("\tiAbsVolRequest = %d, iNotifyRequest = %d"), iAbsVolRequest, iNotifyRequest);
       
   233 	
       
   234 	if ( iNotifyRequest == ESending )
       
   235 		{
       
   236 		iAbsVolSender->Cancel();
       
   237 		}
       
   238 	
       
   239 	iNotificationRequested = EFalse;
       
   240 	RegisterNotifySendComplete();
       
   241 	}
       
   242 
       
   243 TAny* CRemConAbsoluteVolumeController::GetInterfaceIf(TUid aUid)
       
   244     {
       
   245 	LOG_FUNC
       
   246 	
       
   247 	TAny* ret = NULL;
       
   248 	if ( aUid == TUid::Uid(KRemConInterfaceIf2) )
       
   249 		{
       
   250 		ret = reinterpret_cast<TAny*>(
       
   251 			static_cast<MRemConInterfaceIf2*>(this)
       
   252 			);
       
   253 		}
       
   254 	
       
   255 	return ret;
       
   256     }
       
   257 
       
   258 void CRemConAbsoluteVolumeController::MrcibNewMessage(TUint aOperationId, 
       
   259 		const TDesC8& aData, 
       
   260 		TRemConMessageSubType aMessageSubType)
       
   261 	{
       
   262 	LOG_FUNC
       
   263 	LOG2(_L8("\tiAbsVolRequest = %d, iNotifyRequest = %d"), iAbsVolRequest, iNotifyRequest);
       
   264 	
       
   265 	switch (aOperationId)
       
   266 	    {
       
   267 	case KRemConAbsoluteVolumeNotification:
       
   268 		HandleNotify(aData, aMessageSubType);
       
   269 	    break;
       
   270 	case KRemConSetAbsoluteVolume:
       
   271     	HandleSetAbsoluteVolumeResponse(aData);
       
   272 	    break;
       
   273 	default:	   
       
   274 	    break;
       
   275 	    }
       
   276 	}
       
   277 
       
   278 /** 
       
   279 Process the 'volume changed notification response'
       
   280 
       
   281 @param aData The response data.
       
   282 @param aMessageSubType The RemCon submessage type.
       
   283 */
       
   284 void CRemConAbsoluteVolumeController::HandleNotify(const TDesC8& aData,
       
   285 		TRemConMessageSubType aMessageSubType)
       
   286     {
       
   287 	LOG_FUNC
       
   288 	
       
   289     TInt err = KErrNone;
       
   290     
       
   291     if(iNotificationRequested)
       
   292     	{
       
   293 	    RRemConAbsoluteVolumeResponse absVol;
       
   294 	    TRAP(err, absVol.ReadL(aData))
       
   295 	    if (err == KErrNone)
       
   296 	    	{
       
   297 	    	if (absVol.iError == KErrNone)
       
   298 	    		{
       
   299 	    		switch ( aMessageSubType )
       
   300 	    	        {
       
   301 	    	    case ERemConNotifyResponseInterim:
       
   302 	    	    	{
       
   303 	    	    	VolumeUpdate(absVol.iVolume, absVol.iMaxVolume);
       
   304 		    	    break;
       
   305 	    	    	}	    	    
       
   306 	    	    case ERemConNotifyResponseChanged:
       
   307 		    		{
       
   308 	    	    	VolumeUpdate(absVol.iVolume, absVol.iMaxVolume);
       
   309 
       
   310 		    		// Register notification again.
       
   311 		    		iNotificationRequested = EFalse;
       
   312 		    		RegisterAbsoluteVolumeNotification();
       
   313 		    	    break;
       
   314 		    		}	    			
       
   315 	    	    default:    	    
       
   316 	    	        break;
       
   317 	    	        }//switch
       
   318 	    		}
       
   319 	    	else //Error response
       
   320 	    		{
       
   321 	    		iNotificationRequested = EFalse;
       
   322 	    		iObserver.MrcavcoAbsoluteVolumeNotificationError();
       
   323 	    		}
       
   324 	    	}
       
   325 	    else
       
   326 	    	{
       
   327     		iNotificationRequested = EFalse;
       
   328     		iObserver.MrcavcoAbsoluteVolumeNotificationError();
       
   329 	    	}
       
   330     	}
       
   331     }
       
   332 
       
   333 /** 
       
   334 Process the 'set absolute volume response'
       
   335 @param aData The response data.
       
   336 */
       
   337 void CRemConAbsoluteVolumeController::HandleSetAbsoluteVolumeResponse( 
       
   338 		const TDesC8& aData )
       
   339     {
       
   340 	LOG_FUNC
       
   341 	
       
   342     TInt err = KErrNone;
       
   343     RRemConAbsoluteVolumeResponse absVol;
       
   344     TRAP(err, absVol.ReadL(aData))
       
   345     if (err == KErrNone)
       
   346     	{
       
   347     	iCurrentVolume = absVol.iVolume;
       
   348     	iCurrentMaxVolume = absVol.iMaxVolume;
       
   349     	iObserver.MrcavcoSetAbsoluteVolumeResponse(absVol.iVolume, 
       
   350     			absVol.iMaxVolume,
       
   351     			absVol.iError);
       
   352     	}
       
   353     else
       
   354     	{
       
   355     	iObserver.MrcavcoSetAbsoluteVolumeResponse(0, 
       
   356     			0,
       
   357     			err);
       
   358     	}
       
   359     }
       
   360 
       
   361 void CRemConAbsoluteVolumeController::MavsoSendComplete(TInt aResult)
       
   362 	{
       
   363 	LOG_FUNC
       
   364 	LOG1(_L8("\taResult = %d"), aResult);
       
   365 	LOG2(_L8("\tiAbsVolRequest = %d, iNotifyRequest = %d"), iAbsVolRequest, iNotifyRequest);
       
   366 	
       
   367 	if ( iAbsVolRequest == ESending )
       
   368 		{
       
   369 		__ASSERT_DEBUG(iNotifyRequest != ESending, User::Panic(KAbsoluteVolumeControllerFaultName, __LINE__));
       
   370 		SetAbsoluteVolumeSendComplete(aResult);
       
   371 		}
       
   372 	else if ( iNotifyRequest == ESending )
       
   373 		{
       
   374 		// This updates our own state and kicks off any pending send. The 
       
   375 		// later client upcall (if there was an error) gives them a chance 
       
   376 		// to make further calls on us.
       
   377 		RegisterNotifySendComplete();
       
   378 
       
   379 		if(aResult != KErrNone)
       
   380 			{
       
   381 			iNotificationRequested = EFalse;
       
   382 			iObserver.MrcavcoAbsoluteVolumeNotificationError();
       
   383 			}
       
   384 		}
       
   385 	else
       
   386 		{
       
   387 		// Send complete with no send outstanding.
       
   388 		__ASSERT_DEBUG(EFalse, User::Panic(KAbsoluteVolumeControllerFaultName, __LINE__));
       
   389 		}
       
   390 	}
       
   391 
       
   392 void CRemConAbsoluteVolumeController::KickOffSendIfNeeded()
       
   393 	{
       
   394 	LOG_FUNC
       
   395 	LOG2(_L8("\tiAbsVolRequest = %d, iNotifyRequest = %d"), iAbsVolRequest, iNotifyRequest);
       
   396 	
       
   397 	if ( iAbsVolRequest == ESending || iNotifyRequest == ESending )
       
   398 		{
       
   399 		// Any pending send will be kicked off when current send completes and this function is called again.
       
   400 		return;
       
   401 		}
       
   402 		
       
   403 	if ( iAbsVolRequest == EPending )
       
   404 		{
       
   405 		SendSetAbsoluteVolume();
       
   406 		}
       
   407 	else if ( iNotifyRequest == EPending )
       
   408 		{
       
   409 		SendNotify();
       
   410 		}
       
   411 	}
       
   412 
       
   413 void CRemConAbsoluteVolumeController::SetAbsoluteVolumeSendComplete(TInt aResult)
       
   414 	{
       
   415 	LOG_FUNC
       
   416 	LOG1(_L8("\taResult = %d"), aResult);
       
   417 	LOG2(_L8("\tiAbsVolRequest = %d, iNotifyRequest = %d"), iAbsVolRequest, iNotifyRequest);
       
   418 	
       
   419 	__ASSERT_DEBUG(iClientStatus, User::Panic(KAbsoluteVolumeControllerFaultName, __LINE__));
       
   420 	User::RequestComplete(iClientStatus, aResult);
       
   421 	iClientStatus = NULL;
       
   422 	iClientNumRemotes = NULL;
       
   423 	iSetData.SetLength(0);
       
   424 	__ASSERT_DEBUG(iAbsVolRequest != ENotInUse, User::Panic(KAbsoluteVolumeControllerFaultName, __LINE__));
       
   425 	iAbsVolRequest = ENotInUse;
       
   426 	
       
   427 	KickOffSendIfNeeded();
       
   428 	}
       
   429 
       
   430 void CRemConAbsoluteVolumeController::RegisterNotifySendComplete()
       
   431 	{
       
   432 	LOG_FUNC
       
   433 	LOG2(_L8("\tiAbsVolRequest = %d, iNotifyRequest = %d"), iAbsVolRequest, iNotifyRequest);
       
   434 
       
   435 	iNotifyData.SetLength(0);
       
   436 	// This method doesn't actually complete a client request so we don't bother asserting state.
       
   437 	iNotifyRequest = ENotInUse;
       
   438 	
       
   439 	KickOffSendIfNeeded();
       
   440 	}
       
   441 
       
   442 void CRemConAbsoluteVolumeController::VolumeUpdate(TUint32 aVolume, TUint32 aMaxVolume)
       
   443 	{
       
   444 	LOG_FUNC
       
   445 	LOG2(_L8("\taVolume = %d, aMaxVolume = %d"), aVolume, aMaxVolume);
       
   446 	
       
   447 	// Only update the client if the volume has changed
       
   448     if (aVolume != iCurrentVolume || aMaxVolume != iCurrentMaxVolume)
       
   449 	    {
       
   450 	    iCurrentVolume = aVolume; //store the new value
       
   451 	    iCurrentMaxVolume = aMaxVolume;
       
   452 	    
       
   453 	    iObserver.MrcavcoCurrentVolume(aVolume,
       
   454 	    		aMaxVolume,
       
   455 	    		KErrNone);
       
   456 	    }
       
   457 	}
       
   458 
       
   459 void CRemConAbsoluteVolumeController::SendSetAbsoluteVolume()
       
   460 	{
       
   461 	LOG_FUNC
       
   462 	LOG2(_L8("\tiAbsVolRequest = %d, iNotifyRequest = %d"), iAbsVolRequest, iNotifyRequest);
       
   463 	
       
   464 	__ASSERT_DEBUG(iClientNumRemotes, User::Panic(KAbsoluteVolumeControllerFaultName, __LINE__));
       
   465 	iAbsVolSender->SendSetAbsoluteVolume(*iClientNumRemotes, iSetData);
       
   466 	__ASSERT_DEBUG(iAbsVolRequest == EPending, User::Panic(KAbsoluteVolumeControllerFaultName, __LINE__));
       
   467 	iAbsVolRequest = ESending;
       
   468 	}
       
   469 
       
   470 void CRemConAbsoluteVolumeController::SendNotify()
       
   471 	{
       
   472 	LOG_FUNC
       
   473 	LOG2(_L8("\tiAbsVolRequest = %d, iNotifyRequest = %d"), iAbsVolRequest, iNotifyRequest);
       
   474 	
       
   475 	iAbsVolSender->SendNotify(iNotifyData);
       
   476 	__ASSERT_DEBUG(iNotifyRequest == EPending, User::Panic(KAbsoluteVolumeControllerFaultName, __LINE__));
       
   477 	iNotifyRequest = ESending;
       
   478 	}