diff -r 000000000000 -r 79dd3e2336a0 devsound/devsoundrefplugin/tsrc/a3fcistubextn/a3fcistubextn.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/devsound/devsoundrefplugin/tsrc/a3fcistubextn/a3fcistubextn.cpp Fri Oct 08 19:40:43 2010 +0100 @@ -0,0 +1,308 @@ +// 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: +// + +#include "a3fcistubextn.h" +#include +#include +#include "a3fcistubextn.hrh" + +#include +#include +#include +#include +#include + +// +#include "a3fbackdooraccess.h" +#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS +#include +#endif + + +// __________________________________________________________________________ +// Client-side extension + +MDevSoundCIClientExtension* CA3fClientCiStubExtn::NewL() + { + CA3fClientCiStubExtn* self = new (ELeave) CA3fClientCiStubExtn; + return self; + } + +CA3fClientCiStubExtn::~CA3fClientCiStubExtn() + { + delete iDummyBuffer; + REComSession::DestroyedImplementation(iKey); + } + +TInt CA3fClientCiStubExtn::Setup(MCustomCommand& aCustomCommand) + { + iCommand = &aCustomCommand; + iDummyBuffer=KNullDesC().Alloc(); // dummy buffer simulates some allocs + if (!iDummyBuffer) + { + return KErrNoMemory; + } + return KErrNone; + } + +TInt CA3fClientCiStubExtn::CustomInterfaceExtension(TUid aUid, TAny*& aInterface) + { + if (aUid==KUidTestSetVolIf) + { + MTestSetVolIf* interface = this; + aInterface = interface; + return KErrNone; + } + return KErrNotSupported; + } + +void CA3fClientCiStubExtn::Release() + { + delete this; + } + +void CA3fClientCiStubExtn::PassDestructorKey(TUid aDestructorKey) + { + iKey = aDestructorKey; + } + +TInt CA3fClientCiStubExtn::SetVol(TInt aVol) + { + // the key here is the destination package, which represets SetVol. Apart from value + // the rest of the parameters can be ignored + TPckgBuf volumePkg (aVol); + TMMFMessageDestinationPckg setVolDest (TMMFMessageDestination(KUidTestSetVolIf, 0)); + TInt result = iCommand->CustomCommandSync(setVolDest, ETestSetVolIfSetVolCommand, volumePkg, KNullDesC8); + return result; + } + +TInt CA3fClientCiStubExtn::Vol(TInt aMaxVol) + { + // again the key is is the destination package + TPckgBuf maxVolPkg (aMaxVol); + TMMFMessageDestinationPckg setVolDest (TMMFMessageDestination(KUidTestSetVolIf, 0)); + TInt result = iCommand->CustomCommandSync(setVolDest, ETestSetVolIfVolCommand, maxVolPkg, KNullDesC8); + return result; + } + +// __________________________________________________________________________ +// Server-side extension + +MDevSoundCIServerExtension* CA3fServerCiStubExtn::NewL() + { + CA3fServerCiStubExtn* self = new (ELeave) CA3fServerCiStubExtn; + return self; + } + +CA3fServerCiStubExtn::~CA3fServerCiStubExtn() + { + delete iDummyBuffer; + delete iSetVol; + REComSession::DestroyedImplementation(iKey); + } + +TInt CA3fServerCiStubExtn::Setup(MCustomInterface& aCustomInterface) + { + iInterface = &aCustomInterface; + iDummyBuffer=KNullDesC().Alloc(); // dummy buffer simulates some allocs + if (!iDummyBuffer) + { + return KErrNoMemory; + } + return KErrNone; + } + +TInt CA3fServerCiStubExtn::HandleMessageL(const RMmfIpcMessage& aMessage) + { + TMMFMessageDestinationPckg destinationPckg; + MmfMessageUtil::ReadL(aMessage, 0, destinationPckg); + if (destinationPckg().InterfaceId()==KUidTestSetVolIf) + { + CSetVol* volHandler = CSetVol::NewL(*iInterface); + CleanupStack::PushL(volHandler); + TInt result = volHandler->HandleMessageL(aMessage); + CleanupStack::Pop(volHandler); + return result; + } + + return KErrNotSupported; + } + +void CA3fServerCiStubExtn::Release() + { + delete this; + } + +void CA3fServerCiStubExtn::PassDestructorKey(TUid aDestructorKey) + { + iKey = aDestructorKey; + } + +// CSetVol + +CSetVol* CSetVol::NewL(MCustomInterface& aCustomInterface) + { + CSetVol* self = new (ELeave) CSetVol(aCustomInterface); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return self; + } + +CSetVol::CSetVol(MCustomInterface& aCustomInterface): + iInterface(&aCustomInterface) + { + // do nothing + } + +void CSetVol::ConstructL() + { + iWait = new (ELeave) CActiveSchedulerWait(); + } + +CSetVol::~CSetVol() + { + delete iWait; + } + +TInt CSetVol::HandleMessageL(const RMmfIpcMessage& aMessage) + { + switch (aMessage.Function()) + { + case ETestSetVolIfSetVolCommand: + { + TPckgBuf volPckg; + MmfMessageUtil::ReadL(aMessage, 1, volPckg); + UpdateA3fPointers(); // grab pointers to context, stream etc + SetVolumeL(volPckg()); + + User::LeaveIfError(iContext->RegisterAudioContextObserver(*this)); + + TInt error = iContext->Commit(); + if (!error) + { + iError = KErrNone; + iWait->Start(); + error = iError; + } + (void) iContext->UnregisterAudioContextObserver(*this); + + aMessage.Complete(error); + return KErrNone; // KErrNone says we've handled the message + } + case ETestSetVolIfVolCommand: + { + TPckgBuf maxVolPckg; + MmfMessageUtil::ReadL(aMessage, 1, maxVolPckg); + UpdateA3fPointers(); // grab pointers to context, stream etc + TInt result = VolumeL(maxVolPckg()); + aMessage.Complete(result); + return KErrNone; // KErrNone says we've handled the message + } + default: + return KErrArgument; + } + } + +void CSetVol::UpdateA3fPointers() + { + MA3FBackdoorAccessIf* backdoor = + static_cast(iInterface->CustomInterface(KA3FBackdoorAccessIfUid)); + if (backdoor) + { + iContext = backdoor->AudioContext(); + iStream = backdoor->AudioStream(); + iGain = backdoor->ProcessingUnit(KUidAudioGainControl); + } + else + { + iContext = NULL; + iStream = NULL; + iGain = NULL; + } + } + +void CSetVol::SetVolumeL(TInt aVolume) + { + RArray channelGains; + CleanupClosePushL(channelGains); + TAudioChannelGain left; + TAudioChannelGain right; + left.iLocation = TAudioChannelGain::ELeft; + right.iLocation = TAudioChannelGain::ERight; + left.iGain = right.iGain = aVolume; + User::LeaveIfError(channelGains.Append(left)); // assumed element 0 in rest of code + User::LeaveIfError(channelGains.Append(right)); // assumed element 1 in rest of code + + MAudioGainControl* gainControl = static_cast(iGain->Interface(KUidAudioGainControl)); + User::LeaveIfError(gainControl->SetGain(channelGains)); + CleanupStack::PopAndDestroy(&channelGains); + } + +TInt CSetVol::VolumeL(TInt aMaxVolume) + { + RArray channelGains; + CleanupClosePushL(channelGains); + TInt maxGain; + + MAudioGainControl* gainControl = static_cast(iGain->Interface(KUidAudioGainControl)); + User::LeaveIfError(gainControl->GetGain(channelGains)); + User::LeaveIfError(gainControl->GetMaxGain(maxGain)); + + TInt basicVolume = (channelGains[0].iGain + channelGains[1].iGain) / 2; + TInt result = basicVolume * aMaxVolume / maxGain; // scale to 0 to maxVolume + + CleanupStack::PopAndDestroy(&channelGains); + return result; + } + +void CSetVol::ContextEvent(TUid aEvent, TInt aError) + { + if (aEvent==KUidA3FContextUpdateComplete || aEvent==KUidA3FContextAbort) + { + // we are going to assume the SetGain() works and use the end of + // the ContextEvent. Really should observe the gain itself + if (aError) + { + iError = aError; + } + iWait->AsyncStop(); + } + } + +// +// ImplementationTable +// + +const TImplementationProxy ImplementationTable[] = + { + IMPLEMENTATION_PROXY_ENTRY(KUidA3fClientCiStubExtn, CA3fClientCiStubExtn::NewL), + IMPLEMENTATION_PROXY_ENTRY(KUidA3fServerCiStubExtn, CA3fServerCiStubExtn::NewL), + }; + + +// +// ImplementationGroupProxy +// +// + +EXPORT_C const TImplementationProxy* ImplementationGroupProxy(TInt& aTableCount) + { + aTableCount = sizeof(ImplementationTable) / sizeof(TImplementationProxy); + + return ImplementationTable; + } + +