devsound/sounddevbt/src/A2dpBlueTooth/server/A2dpBTHeadsetAudioIfServer.cpp
changeset 0 40261b775718
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/devsound/sounddevbt/src/A2dpBlueTooth/server/A2dpBTHeadsetAudioIfServer.cpp	Tue Feb 02 01:56:55 2010 +0200
@@ -0,0 +1,520 @@
+// Copyright (c) 2005-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:
+//
+
+#include <s32mem.h>
+#include "A2dpBTHeadsetAudioIfServer.h"
+#include "A2dpBTHeadsetAudioIfServerStart.h"
+#include "A2dpBTheadsetAudioIf.h"
+#include "MMFBtRoutingSoundDevice.h"	// for TRange
+
+
+CA2dpBTHeadsetAudioIfServer* CA2dpBTHeadsetAudioIfServer::NewL()
+	{
+	CA2dpBTHeadsetAudioIfServer* self = new(ELeave) CA2dpBTHeadsetAudioIfServer();
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop();
+	return self;
+	}
+	
+CA2dpBTHeadsetAudioIfServer::~CA2dpBTHeadsetAudioIfServer()
+	{
+	delete iBTAudioInterface;
+	}
+	
+CMmfIpcSession* CA2dpBTHeadsetAudioIfServer::NewSessionL(const TVersion &aVersion) const
+	{
+	TVersion version(	KBTAudioServerMajorVersionNumber,
+						KBTAudioServerMinorVersionNumber,
+						KBTAudioServerBuildVersionNumber);
+
+	if(!User::QueryVersionSupported(version, aVersion))
+		{
+		User::Leave(KErrNotSupported);
+		}
+	
+	CA2dpBTHeadsetAudioIfSession* session = CA2dpBTHeadsetAudioIfSession::NewL(iBTAudioInterface);
+	return session;
+	}
+
+CA2dpBTHeadsetAudioIfServer::CA2dpBTHeadsetAudioIfServer() :
+							 CMmfIpcServer(EPriorityStandard)
+	{
+	}
+	
+void CA2dpBTHeadsetAudioIfServer::ConstructL()
+	{
+	// Create the interface to the BT headset
+	iBTAudioInterface = CA2dpBTHeadsetAudioInterface::NewL();
+	
+	// Call base class to Start server
+	TName name(RThread().Name());
+	StartL(name);
+	}
+
+
+/*
+ Session implementation.
+ */
+CA2dpBTHeadsetAudioIfSession* CA2dpBTHeadsetAudioIfSession::NewL( CA2dpBTHeadsetAudioInterface* 
+																	aBTAudioInterface)
+	{
+	CA2dpBTHeadsetAudioIfSession* self = new(ELeave) CA2dpBTHeadsetAudioIfSession(aBTAudioInterface);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop(self);
+	return self;
+	}
+	
+CA2dpBTHeadsetAudioIfSession::CA2dpBTHeadsetAudioIfSession(CA2dpBTHeadsetAudioInterface* aBTAudioInterface) :
+							iBTAudioInterface(aBTAudioInterface)
+	{
+	}
+
+void CA2dpBTHeadsetAudioIfSession::ConstructL()
+	{
+	// Create the AO event handlers
+	iInitHandler = CA2dpBTHeadsetIfEventHandler::NewL();
+	iOpenDeviceHandler = CA2dpBTHeadsetIfEventHandler::NewL();
+	iCloseDeviceHandler = CA2dpBTHeadsetIfEventHandler::NewL();
+	iPlayDataHandler = CA2dpBTHeadsetIfEventHandler::NewL();
+	iNotifyErrorHandler = CA2dpBTHeadsetIfEventHandler::NewL();
+	}
+
+CA2dpBTHeadsetAudioIfSession::~CA2dpBTHeadsetAudioIfSession()
+	{
+	delete iInitHandler;
+	delete iOpenDeviceHandler;
+	delete iCloseDeviceHandler;
+	delete iPlayDataHandler;
+	delete iNotifyErrorHandler;
+	}
+	
+void CA2dpBTHeadsetAudioIfSession::ServiceL(const RMessage2& aMessage)
+	{
+	// Service the message
+	TBool complete = EFalse;
+	TInt err = KErrNone;
+	switch(aMessage.Function())
+		{
+	case EBTAudioServerInitialize:
+		complete = DoInitializeL(aMessage);
+		break;
+	case EBTAudioServerCancelInitialize:
+		complete = DoCancelInitializeL(aMessage);
+		break;
+	case EBTAudioServerCopyFourCCArrayData:
+		complete = DoCopyFourCCArrayDataL(aMessage);
+		break;
+	case EBTAudioServerCopyChannelsArrayData:
+		complete = DoCopyChannelsArrayDataL(aMessage);
+		break;
+	case EBTAudioServerGetSupportedDataTypes:
+		err = DoGetSupportedDataTypesL(aMessage);
+		aMessage.Complete(err);
+		break;
+	case EBTAudioServerGetSupportedSampleRates:
+		err = DoGetSupportedSampleRatesL(aMessage);
+		aMessage.Complete(err);
+		break;
+	case EBTAudioServerGetSupportedSampleRatesDiscrete:
+		complete = DoGetSupportedSampleRatesDiscreteL(aMessage);
+		break;
+	case EBTAudioServerGetSupportedSampleRatesRange:
+		complete = DoGetSupportedSampleRatesRangeL(aMessage);
+		break;
+	case EBTAudioServerGetSupportedChannels:
+		err = DoGetSupportedChannelsL(aMessage);
+		aMessage.Complete(err);
+		break;
+	case EBTAudioServerSetDataType:
+		err = DoSetDataTypeL(aMessage);
+		aMessage.Complete(err);
+		break;
+	case EBTAudioServerSetSampleRate:
+		err = DoSetSampleRateL(aMessage);
+		aMessage.Complete(err);
+		break;
+	case EBTAudioServerSetChannels:
+		err = DoSetChannelsL(aMessage);
+		aMessage.Complete(err);
+		break;
+	case EBTAudioServerOpenDevice:
+		complete = DoOpenDeviceL(aMessage);
+		break;
+	case EBTAudioServerCancelOpenDevice:
+		complete = DoCancelOpenDevice(aMessage);
+		break;
+	case EBTAudioServerCloseDevice:
+		complete = DoCloseDeviceL(aMessage);
+		break;
+	case EBTAudioServerVolume:
+		complete = DoVolumeL(aMessage);
+		break;
+	case EBTAudioServerSetVolume:
+		err = DoSetVolumeL(aMessage);
+		aMessage.Complete(err);
+		break;
+	case EBTAudioServerPlayData:
+		complete = DoPlayDataL(aMessage);
+		break;
+	case EBTAudioServerCancelPlayData:
+		complete = DoCancelPlayDataL(aMessage);
+		break;
+	case EBTAudioServerFlushBuffer:
+		complete = DoFlushBufferL(aMessage);
+		break;
+	case EBTAudioServerBytesPlayed:
+		complete = DoBytesPlayedL(aMessage);
+		break;
+	case EBTAudioServerResetBytesPlayed:
+		complete = DoResetBytesPlayedL(aMessage);
+		break;
+	case EBTAudioServerPauseBuffer:
+		complete = DoPauseBufferL(aMessage);
+		break;
+	case EBTAudioServerResumePlaying:
+		complete = DoResumePlayingL(aMessage);
+		break;
+	case EBTAudioServerNotifyError:
+		complete = DoNotifyErrorL(aMessage);
+		break;
+	case EBTAudioServerCancelNotifyError:
+		complete = DoCancelNotifyErrorL(aMessage);
+		break;
+	default:
+		User::Leave(KErrNotSupported);
+		break;
+		}
+
+	if (complete)
+		{
+		aMessage.Complete(KErrNone);
+		}
+	}
+
+TBool CA2dpBTHeadsetAudioIfSession::DoInitializeL(const RMmfIpcMessage& aMessage)
+	{
+	// Get the address from the message
+	TPckgBuf<TBTDevAddr> btAddrPckg;
+	aMessage.ReadL(0, btAddrPckg);
+	TBTDevAddr& devAddr = btAddrPckg();
+	iInitHandler->StartL(aMessage);
+	iBTAudioInterface->Initialize(devAddr, iInitHandler->iStatus);
+		
+	return EFalse;
+	}
+
+TBool CA2dpBTHeadsetAudioIfSession::DoCancelInitializeL(const RMmfIpcMessage& /*aMessage*/)
+	{
+	iBTAudioInterface->CancelInitialize();
+	iInitHandler->Stop();
+	return ETrue;
+	}
+
+TBool CA2dpBTHeadsetAudioIfSession::DoCopyFourCCArrayDataL(const RMmfIpcMessage& aMessage)
+	{
+	const TInt KBufExpandSize8 = 8;//two TInts
+	CBufFlat* dataCopyBuffer = CBufFlat::NewL(KBufExpandSize8);
+	CleanupStack::PushL(dataCopyBuffer);
+	RBufWriteStream stream;
+	stream.Open(*dataCopyBuffer);
+	CleanupClosePushL(stream);
+	for (TInt i = 0; i < iFourCCArray.Count(); i++)
+		{
+		stream.WriteInt32L(iFourCCArray[i].FourCC());
+		}
+	aMessage.WriteL(0, dataCopyBuffer->Ptr(0));
+	stream.Close();
+	CleanupStack::PopAndDestroy(2);//dataCopyBuffer, stream
+	return ETrue;
+	}
+
+TBool CA2dpBTHeadsetAudioIfSession::DoCopyUintArrayDataL(const RMmfIpcMessage& aMessage, RArray<TUint> aArray)
+	{
+	const TInt KBufExpandSize8 = 8;//two TInts
+	CBufFlat* dataCopyBuffer = CBufFlat::NewL(KBufExpandSize8);
+	CleanupStack::PushL(dataCopyBuffer);
+	RBufWriteStream stream;
+	stream.Open(*dataCopyBuffer);
+	CleanupClosePushL(stream);
+	for (TInt i = 0; i < aArray.Count(); i++)
+		{
+		stream.WriteInt32L(aArray[i]);
+		}
+	aMessage.WriteL(0, dataCopyBuffer->Ptr(0));
+	stream.Close();
+	CleanupStack::PopAndDestroy(2);//dataCopyBuffer, stream	
+	return ETrue;
+	}
+
+TInt CA2dpBTHeadsetAudioIfSession::DoGetSupportedDataTypesL(const RMmfIpcMessage& aMessage)
+	{
+	iFourCCArray.Reset();
+
+	TInt err = iBTAudioInterface->GetSupportedDataTypes(iFourCCArray);
+
+	TPckgBuf<TInt> pckg;
+	pckg() = iFourCCArray.Count();
+	aMessage.WriteL(TInt(0),pckg);	
+	
+	return err;
+	}
+
+TInt CA2dpBTHeadsetAudioIfSession::DoGetSupportedSampleRatesL(const RMmfIpcMessage& aMessage)
+	{
+	iDiscreteArray.Reset();
+	iRangeArray.Reset();
+	
+	TInt err = iBTAudioInterface->GetSupportedSampleRates(iDiscreteArray, iRangeArray);
+	
+	TPckgBuf<TRatesArrayElements> pckg;
+	pckg().iDiscrete = iDiscreteArray.Count();
+	pckg().iRange = iRangeArray.Count();
+	
+	aMessage.WriteL(0, pckg);
+	
+	return err;
+	}
+
+TBool CA2dpBTHeadsetAudioIfSession::DoGetSupportedSampleRatesDiscreteL(const RMmfIpcMessage& aMessage)
+	{
+	return DoCopyUintArrayDataL(aMessage, iDiscreteArray);
+	}
+
+TBool CA2dpBTHeadsetAudioIfSession::DoGetSupportedSampleRatesRangeL(const RMmfIpcMessage& aMessage)
+	{
+	const TInt KBufExpandSize8 = 8;//two TInts
+	CBufFlat* dataCopyBuffer = CBufFlat::NewL(KBufExpandSize8);
+	CleanupStack::PushL(dataCopyBuffer);
+	RBufWriteStream stream;
+	stream.Open(*dataCopyBuffer);
+	CleanupClosePushL(stream);
+	for (TInt i = 0; i < iRangeArray.Count(); i++)
+		{
+		stream.WriteInt32L(iRangeArray[i].iLow);
+		stream.WriteInt32L(iRangeArray[i].iHigh);
+		}
+	aMessage.WriteL(0, dataCopyBuffer->Ptr(0));
+	stream.Close();
+	CleanupStack::PopAndDestroy(2);//dataCopyBuffer, stream
+	return ETrue;
+	}
+
+TInt CA2dpBTHeadsetAudioIfSession::DoGetSupportedChannelsL(const RMmfIpcMessage& aMessage)
+	{
+	// Array of uints
+	iStereoSupportArray.Reset();
+	TMMFStereoSupport stereoSupport;
+
+	TInt err = iBTAudioInterface->GetSupportedChannels(iStereoSupportArray, stereoSupport);
+	
+	TPckgBuf<TChannelsSupport> pckg;
+	pckg().iElementCount = iStereoSupportArray.Count();
+	pckg().iSupport = stereoSupport;
+	
+	aMessage.WriteL(0, pckg);
+	
+	return err;
+	}
+
+TBool CA2dpBTHeadsetAudioIfSession::DoCopyChannelsArrayDataL(const RMmfIpcMessage& aMessage)
+	{
+	return DoCopyUintArrayDataL(aMessage, iStereoSupportArray);
+	}
+
+TInt CA2dpBTHeadsetAudioIfSession::DoSetDataTypeL(const RMmfIpcMessage& aMessage)
+	{
+	TPckgBuf<TFourCC> dataTypePckg;
+	aMessage.ReadL(0, dataTypePckg);
+	TFourCC dataType = dataTypePckg();
+	return iBTAudioInterface->SetDataType(dataType);
+	}
+
+TInt CA2dpBTHeadsetAudioIfSession::DoSetSampleRateL(const RMmfIpcMessage& aMessage)
+	{
+	TPckgBuf<TUint> ratePckg;
+	aMessage.ReadL(0, ratePckg);
+	TUint rate = ratePckg();
+	return iBTAudioInterface->SetSampleRate(rate);
+	}
+
+TInt CA2dpBTHeadsetAudioIfSession::DoSetChannelsL(const RMmfIpcMessage& aMessage)
+	{
+	TPckgBuf<TChannelsSupport> pckgBuf;
+	aMessage.ReadL(0, pckgBuf);
+	TChannelsSupport support = pckgBuf();
+	return iBTAudioInterface->SetChannels(support.iElementCount, support.iSupport);
+	}
+
+TBool CA2dpBTHeadsetAudioIfSession::DoOpenDeviceL(const RMmfIpcMessage& aMessage)
+	{
+	iOpenDeviceHandler->StartL(aMessage);
+	iBTAudioInterface->OpenDevice(iOpenDeviceHandler->iStatus);
+	return EFalse;
+	}
+
+TBool CA2dpBTHeadsetAudioIfSession::DoCancelOpenDevice(const RMmfIpcMessage& /*aMessage*/)
+	{
+	iBTAudioInterface->CancelOpenDevice();
+	return ETrue;
+	}
+	
+TBool CA2dpBTHeadsetAudioIfSession::DoCloseDeviceL(const RMmfIpcMessage& aMessage)
+	{
+	iCloseDeviceHandler->StartL(aMessage);
+	iBTAudioInterface->CloseDevice(iCloseDeviceHandler->iStatus);
+	return EFalse;
+	}
+
+TBool CA2dpBTHeadsetAudioIfSession::DoVolumeL(const RMmfIpcMessage& aMessage)
+	{	
+	TUint volume = iBTAudioInterface->Volume();
+	TPckgBuf<TUint> pckg(volume);
+	aMessage.WriteL(0, pckg);
+	return ETrue;
+	}
+
+TInt CA2dpBTHeadsetAudioIfSession::DoSetVolumeL(const RMmfIpcMessage& aMessage)
+	{
+	TPckgBuf<TUint> pckg;
+	aMessage.ReadL(0, pckg);
+	TUint volume = pckg();
+	return iBTAudioInterface->SetVolume(volume);
+	}
+
+TBool CA2dpBTHeadsetAudioIfSession::DoPlayDataL(const RMmfIpcMessage& aMessage)
+	{
+	// Client's in the same process so access the buffer directly
+	const TPtr8* ptr = static_cast<const TPtr8*>(aMessage.Ptr0());
+	iPlayDataHandler->StartL(aMessage);
+	iBTAudioInterface->PlayData(*ptr, iPlayDataHandler->iStatus);
+	return EFalse;
+	}
+
+TBool CA2dpBTHeadsetAudioIfSession::DoCancelPlayDataL(const RMmfIpcMessage& /*aMessage*/)
+	{
+	iBTAudioInterface->CancelPlayData();
+	iPlayDataHandler->Stop();
+	return ETrue;
+	}
+
+TBool CA2dpBTHeadsetAudioIfSession::DoFlushBufferL(const RMmfIpcMessage& /*aMessage*/)
+	{
+	iBTAudioInterface->FlushBuffer();
+	return ETrue;
+	}
+
+TBool CA2dpBTHeadsetAudioIfSession::DoBytesPlayedL(const RMmfIpcMessage& aMessage)
+	{
+	TUint bytesPlayed = iBTAudioInterface->BytesPlayed();
+	TPckgBuf<TUint> pckg(bytesPlayed);
+	aMessage.WriteL(0, pckg);
+	return ETrue;
+	}
+
+TBool CA2dpBTHeadsetAudioIfSession::DoResetBytesPlayedL(const RMmfIpcMessage& /*aMessage*/)
+	{
+	iBTAudioInterface->ResetBytesPlayed();
+	return ETrue;
+	}
+
+TBool CA2dpBTHeadsetAudioIfSession::DoPauseBufferL(const RMmfIpcMessage& /*aMessage*/)
+	{
+	iBTAudioInterface->PauseBuffer();
+	return ETrue;
+	}
+
+TBool CA2dpBTHeadsetAudioIfSession::DoResumePlayingL(const RMmfIpcMessage& /*aMessage*/)
+	{
+	iBTAudioInterface->ResumePlaying();
+	return ETrue;
+	}
+
+TBool CA2dpBTHeadsetAudioIfSession::DoNotifyErrorL(const RMmfIpcMessage& aMessage)
+	{
+	iNotifyErrorHandler->StartL(aMessage);
+	iBTAudioInterface->NotifyError(iNotifyErrorHandler->iStatus);
+	return EFalse;
+	}
+
+TBool CA2dpBTHeadsetAudioIfSession::DoCancelNotifyErrorL(const RMmfIpcMessage& /*aMessage*/)
+	{
+	iBTAudioInterface->CancelNotifyError();
+	iNotifyErrorHandler->Stop();
+	return ETrue;
+	}
+
+/**
+ * Implementation of Active Object to handle asynch requests to the Bluetooth interface.
+ */
+CA2dpBTHeadsetIfEventHandler* CA2dpBTHeadsetIfEventHandler::NewL()
+	{
+	CA2dpBTHeadsetIfEventHandler* self = new(ELeave) CA2dpBTHeadsetIfEventHandler();
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop(self);
+	return self;
+	}
+	
+CA2dpBTHeadsetIfEventHandler::~CA2dpBTHeadsetIfEventHandler()
+	{
+	Cancel();
+	delete iMessage;
+	}
+
+void CA2dpBTHeadsetIfEventHandler::RunL()
+	{
+	TInt err = iStatus.Int();
+	// Complete the message
+	iMessage->Complete(err);
+	delete iMessage;
+	iMessage = NULL;
+	}
+
+void CA2dpBTHeadsetIfEventHandler::DoCancel()
+	{
+	if (iMessage)
+		{
+		iMessage->Complete(KErrCancel);		
+		}
+	}
+	
+CA2dpBTHeadsetIfEventHandler::CA2dpBTHeadsetIfEventHandler() : CActive(EPriorityStandard)
+	{
+	CActiveScheduler::Add(this);
+	}
+
+void CA2dpBTHeadsetIfEventHandler::ConstructL()
+	{
+	}
+
+void CA2dpBTHeadsetIfEventHandler::StartL(const RMmfIpcMessage& aMessage)
+	{
+	// take a copy of the message to complete later
+	delete iMessage;	// ensure we only have one message!
+	iMessage = NULL;
+	iMessage = new(ELeave) RMmfIpcMessage(aMessage);
+
+	if (!IsActive())
+		{
+		SetActive();
+		}
+	}
+	
+void CA2dpBTHeadsetIfEventHandler::Stop()
+	{
+	Cancel();
+	}