remotecontrol/avrcp/absolutevolumeapi/src/absolutevolumeapitarget.cpp
author hgs
Wed, 13 Oct 2010 16:20:29 +0300
changeset 51 20ac952a623c
permissions -rw-r--r--
201040_02

// Copyright (c) 2008-2009 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:
//



/**
 @file
 @publishedAll
 @released
*/

#include <absolutevolumeapitarget.h>
#include <absolutevolumeapitargetobserver.h>
#include <remconinterfaceselector.h>
#include <absolutevolumeapi.h>
#include <absolutevolumeutils.h>
#include <bluetooth/logger.h>

#ifdef __FLOG_ACTIVE
_LIT8(KLogComponent, LOG_COMPONENT_REMCONABSOLUTEVOLUME);
_LIT8(KLogFormat, "Operation Id = 0x%x, Data Lengh = %d");
_LIT8(KLogNewL, "CRemConAbsoluteVolumeTarget::NewL");
#endif

/**
Allocates and constructs a new CRemConAbsoluteVolumeTarget object

@param aInterfaceSelector The interface selector. The client must have 
       created one of these first.
@param aObserver The observer through which the client will receive absolute
       volume commands from M class MRemConAbsoluteVolumeTargetObserver.
@param aVolume The initial relative volume on the client.
@param aMaxVolume The client maximum volume against which aVolume is relative.
@return A new CRemConAbsoluteVolumeTarget, owned by the interface selector.
@panic AbsoluteVolumeTarget 0 if aMaxVolume is zero
       AbsoluteVolumeTarget 1 if aVolume greater than aMaxVolume
       
*/
EXPORT_C CRemConAbsoluteVolumeTarget* CRemConAbsoluteVolumeTarget::NewL(
		CRemConInterfaceSelector& aInterfaceSelector, 
		MRemConAbsoluteVolumeTargetObserver& aObserver,
		TUint32 aVolume, 
		TUint32 aMaxVolume)
	{
	LOG(KLogNewL);
	
	__ASSERT_ALWAYS(aMaxVolume > 0, 
			User::Panic(KAbsoluteVolumeTargetPanicName, 
					ETargetInvalidMaxVolume)
			);
	__ASSERT_ALWAYS(aVolume <= aMaxVolume, 
			User::Panic(KAbsoluteVolumeTargetPanicName, 
					ETargetVolumeBeyondMaxVolume)
			);
	
	CRemConAbsoluteVolumeTarget* self = 
	new(ELeave) CRemConAbsoluteVolumeTarget(aInterfaceSelector, 
			aObserver, aVolume, aMaxVolume);
	
	CleanupStack::PushL(self);
	self->ConstructL();
	CleanupStack::Pop(self);
	return self;
	}

/** 
Constructor.
@param aInterfaceSelector The interface selector.
@param aObserver The observer of this interface.
@param aVolume The initial relative volume on the client
@param aMaxVolume The maximum volume on the client against which 
       aVolume is relative.
*/
CRemConAbsoluteVolumeTarget::CRemConAbsoluteVolumeTarget(
		CRemConInterfaceSelector& aInterfaceSelector, 
		MRemConAbsoluteVolumeTargetObserver& aObserver,
		TUint32 aVolume, 
		TUint32 aMaxVolume)
:	CRemConInterfaceBase(TUid::Uid(KRemConAbsoluteVolumeTargetApiUid),
		KAbsoluteVolumeRequestDataSize, 
		aInterfaceSelector,
		ERemConClientTypeTarget), 
	iObserver(aObserver),
	iAbsoluteVolumeNotificationRequest(EFalse),
	iClientVolume(aVolume),
	iClientMaxVolume(aMaxVolume)
	{
	}
	
void CRemConAbsoluteVolumeTarget::ConstructL()
	{
	iOutBuf.CreateL(KAbsoluteVolumeResponseDataSize);

	//Mandate the following features supported.
	RRemConInterfaceFeatures features;
	User::LeaveIfError(features.Open());
	CleanupClosePushL(features);
	features.AddOperationL(KRemConSetAbsoluteVolume);
	
	BaseConstructL(features);
	CleanupStack::PopAndDestroy(&features);
	}

EXPORT_C CRemConAbsoluteVolumeTarget::~CRemConAbsoluteVolumeTarget()
	{
	iOutBuf.Close();
	}

TAny* CRemConAbsoluteVolumeTarget::GetInterfaceIf(TUid aUid)
	{
	TAny* ret = NULL;
	if ( aUid == TUid::Uid(KRemConInterfaceIf2) )
		{
		ret = reinterpret_cast<TAny*>(
			static_cast<MRemConInterfaceIf2*>(this)
			);
		}

	return ret;
	}

/** 
Called by the client in response to a MrcavtoSetAbsoluteVolume() call.

@param aVolume The relative volume against the client maximum volume.  
@param aErr The error code.
     - KErrNone if the client has changed its absolute volume.
     - System wide error code otherwise.
@panic AbsoluteVolumeTarget 1, if volume is greater than max volume.
*/
EXPORT_C void CRemConAbsoluteVolumeTarget::SetAbsoluteVolumeResponse(
		TUint32 aVolume, 
		TInt aErr)
	{
	__ASSERT_ALWAYS(aVolume <= iClientMaxVolume, 
			User::Panic(KAbsoluteVolumeTargetPanicName, 
					ETargetVolumeBeyondMaxVolume)
			);
	
	RRemConAbsoluteVolumeResponse response;
	response.iError = KErrNone;
	response.iVolume = aVolume;
	response.iMaxVolume = iClientMaxVolume;
	TRAPD(error, response.WriteL(iOutBuf));
	if (error != KErrNone)
		{
		SendError(KErrAbsoluteVolumeInternalError, KRemConSetAbsoluteVolume);
		return;
		}
	
	if (aErr == KErrNone)
		{
		// send the response back to the CT
		error = InterfaceSelector().SendUnreliable(
				TUid::Uid(KRemConAbsoluteVolumeTargetApiUid),
				KRemConSetAbsoluteVolume, ERemConResponse, iOutBuf );
		}
	else
		{
		SendError(KErrAbsoluteVolumeInternalError, KRemConSetAbsoluteVolume);
		}
	}

/** 
Must be called each time the volume changes on the client.

It is used to inform the controller if it has requested updates on the client
volume change.

@param aVolume The relative volume against the client maximum volume. 
@panic AbsoluteVolume 1, if volume greater than the client max volume.
*/
EXPORT_C void CRemConAbsoluteVolumeTarget::AbsoluteVolumeChanged(
		TUint32 aVolume)
	{
	__ASSERT_ALWAYS(aVolume <= iClientMaxVolume, 
			User::Panic(KAbsoluteVolumeTargetPanicName, 
					ETargetVolumeBeyondMaxVolume)
			);
	
	if (aVolume != iClientVolume)
		{
		// Records the current volume each time
		// when the client absolute volume is changed
		iClientVolume = aVolume;
		
		if (iAbsoluteVolumeNotificationRequest)
			{
			iAbsoluteVolumeNotificationRequest = EFalse;
			SendNotificationResponse(ERemConNotifyResponseChanged);
			}
		}
	}

// From MRemConInterfaceIf
void CRemConAbsoluteVolumeTarget::SendError(TInt aError, TUint aOperationId)
	{
	TInt error = KErrNone;
	RRemConAbsoluteVolumeResponse errRsp;
	errRsp.iError = aError;
	TRAP(error, errRsp.WriteL(iOutBuf));
	if (error == KErrNone)
		{
		InterfaceSelector().SendUnreliable(
				TUid::Uid(KRemConAbsoluteVolumeTargetApiUid),
				aOperationId, ERemConResponse, iOutBuf);
		}
	}

void CRemConAbsoluteVolumeTarget::MrcibNewMessage(TUint aOperationId, 
		const TDesC8& aData, 
		TRemConMessageSubType aMsgSubType)
	{
	LOG_FUNC
	LOG2(KLogFormat, aOperationId, aData.Length());

	switch(aOperationId)
		{
	case KRemConSetAbsoluteVolume:
		{
		ProcessSetAbsoluteVolume(aData);
		break;
		}
	case KRemConAbsoluteVolumeNotification:
		{
		// register for Notifications
		if (aMsgSubType == ERemConNotifyCommandAwaitingInterim)
			{
			ProcessGetStatusAndBeginObserving();
			}
		else if (aMsgSubType == ERemConNotifyCommandAwaitingChanged)
			{
			ProcessGetStatus();
			}
	 	break;
		}
	default:
		break; 
		};
	}

/**
Processes the request for setting absolute volume.

@param aData The absolute volume data to be setted.
*/
void CRemConAbsoluteVolumeTarget::ProcessSetAbsoluteVolume(
		const TDesC8& aData)
	{	
	TInt error;
	RRemConAbsoluteVolumeRequest request;
	TRAP(error, request.ReadL(aData));
	if ( error == KErrNone)
		{
		iObserver.MrcavtoSetAbsoluteVolumeRequest(request.iVolume, 
				request.iMaxVolume);
		}
	else
		{
		SendError(KErrAbsoluteVolumeInternalError, KRemConSetAbsoluteVolume);
		}
	}

/**
Processes the request for notify command waiting interim.
*/
void CRemConAbsoluteVolumeTarget::ProcessGetStatusAndBeginObserving()
	{
	//Flag is ETure to indicate the request for absolute volume change 
	//notification has been received.
	iAbsoluteVolumeNotificationRequest = ETrue;
		
	//send the interim response with the current absolute volume.
	SendNotificationResponse(ERemConNotifyResponseInterim);
	}

/**
Processes the request for notify command waiting changed.
*/
void CRemConAbsoluteVolumeTarget::ProcessGetStatus()
	{
	// send the current value
	SendNotificationResponse(ERemConNotifyResponseChanged);
	}

/**
Sends absolute volume interim or change response according to the message 
type aMsgSubType

@param aMsgSubType The remcon submessage type.
*/
void CRemConAbsoluteVolumeTarget::SendNotificationResponse(
		TRemConMessageSubType aMsgSubType)
	{
	LOG_FUNC

	TInt error = 0;
	RRemConAbsoluteVolumeResponse response;
	response.iError = KErrNone;
	response.iVolume = iClientVolume;
	response.iMaxVolume = iClientMaxVolume;
	TRAP(error, response.WriteL(iOutBuf));
	if (error == KErrNone)
		{
		error = InterfaceSelector().SendUnreliable(
				TUid::Uid(KRemConAbsoluteVolumeTargetApiUid),
				KRemConAbsoluteVolumeNotification, 
				ERemConResponse, 
				aMsgSubType,
				iOutBuf);
		}
	}