sl@0: // Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // sl@0: sl@0: #include "a3fcistubextn.h" sl@0: #include <ecom/ecom.h> sl@0: #include <ecom/implementationproxy.h> sl@0: #include "a3fcistubextn.hrh" sl@0: sl@0: #include <a3f/maudiocontext.h> sl@0: #include <a3f/maudiostream.h> sl@0: #include <a3f/maudioprocessingunit.h> sl@0: #include <a3f/maudiogaincontrol.h> sl@0: #include <a3f/audioprocessingunittypeuids.h> sl@0: sl@0: // sl@0: #include "a3fbackdooraccess.h" sl@0: #ifdef SYMBIAN_ENABLE_SPLIT_HEADERS sl@0: #include <mmf/common/mmfipcserver.h> sl@0: #endif sl@0: sl@0: sl@0: // __________________________________________________________________________ sl@0: // Client-side extension sl@0: sl@0: MDevSoundCIClientExtension* CA3fClientCiStubExtn::NewL() sl@0: { sl@0: CA3fClientCiStubExtn* self = new (ELeave) CA3fClientCiStubExtn; sl@0: return self; sl@0: } sl@0: sl@0: CA3fClientCiStubExtn::~CA3fClientCiStubExtn() sl@0: { sl@0: delete iDummyBuffer; sl@0: REComSession::DestroyedImplementation(iKey); sl@0: } sl@0: sl@0: TInt CA3fClientCiStubExtn::Setup(MCustomCommand& aCustomCommand) sl@0: { sl@0: iCommand = &aCustomCommand; sl@0: iDummyBuffer=KNullDesC().Alloc(); // dummy buffer simulates some allocs sl@0: if (!iDummyBuffer) sl@0: { sl@0: return KErrNoMemory; sl@0: } sl@0: return KErrNone; sl@0: } sl@0: sl@0: TInt CA3fClientCiStubExtn::CustomInterfaceExtension(TUid aUid, TAny*& aInterface) sl@0: { sl@0: if (aUid==KUidTestSetVolIf) sl@0: { sl@0: MTestSetVolIf* interface = this; sl@0: aInterface = interface; sl@0: return KErrNone; sl@0: } sl@0: return KErrNotSupported; sl@0: } sl@0: sl@0: void CA3fClientCiStubExtn::Release() sl@0: { sl@0: delete this; sl@0: } sl@0: sl@0: void CA3fClientCiStubExtn::PassDestructorKey(TUid aDestructorKey) sl@0: { sl@0: iKey = aDestructorKey; sl@0: } sl@0: sl@0: TInt CA3fClientCiStubExtn::SetVol(TInt aVol) sl@0: { sl@0: // the key here is the destination package, which represets SetVol. Apart from value sl@0: // the rest of the parameters can be ignored sl@0: TPckgBuf<TInt> volumePkg (aVol); sl@0: TMMFMessageDestinationPckg setVolDest (TMMFMessageDestination(KUidTestSetVolIf, 0)); sl@0: TInt result = iCommand->CustomCommandSync(setVolDest, ETestSetVolIfSetVolCommand, volumePkg, KNullDesC8); sl@0: return result; sl@0: } sl@0: sl@0: TInt CA3fClientCiStubExtn::Vol(TInt aMaxVol) sl@0: { sl@0: // again the key is is the destination package sl@0: TPckgBuf<TInt> maxVolPkg (aMaxVol); sl@0: TMMFMessageDestinationPckg setVolDest (TMMFMessageDestination(KUidTestSetVolIf, 0)); sl@0: TInt result = iCommand->CustomCommandSync(setVolDest, ETestSetVolIfVolCommand, maxVolPkg, KNullDesC8); sl@0: return result; sl@0: } sl@0: sl@0: // __________________________________________________________________________ sl@0: // Server-side extension sl@0: sl@0: MDevSoundCIServerExtension* CA3fServerCiStubExtn::NewL() sl@0: { sl@0: CA3fServerCiStubExtn* self = new (ELeave) CA3fServerCiStubExtn; sl@0: return self; sl@0: } sl@0: sl@0: CA3fServerCiStubExtn::~CA3fServerCiStubExtn() sl@0: { sl@0: delete iDummyBuffer; sl@0: delete iSetVol; sl@0: REComSession::DestroyedImplementation(iKey); sl@0: } sl@0: sl@0: TInt CA3fServerCiStubExtn::Setup(MCustomInterface& aCustomInterface) sl@0: { sl@0: iInterface = &aCustomInterface; sl@0: iDummyBuffer=KNullDesC().Alloc(); // dummy buffer simulates some allocs sl@0: if (!iDummyBuffer) sl@0: { sl@0: return KErrNoMemory; sl@0: } sl@0: return KErrNone; sl@0: } sl@0: sl@0: TInt CA3fServerCiStubExtn::HandleMessageL(const RMmfIpcMessage& aMessage) sl@0: { sl@0: TMMFMessageDestinationPckg destinationPckg; sl@0: MmfMessageUtil::ReadL(aMessage, 0, destinationPckg); sl@0: if (destinationPckg().InterfaceId()==KUidTestSetVolIf) sl@0: { sl@0: CSetVol* volHandler = CSetVol::NewL(*iInterface); sl@0: CleanupStack::PushL(volHandler); sl@0: TInt result = volHandler->HandleMessageL(aMessage); sl@0: CleanupStack::Pop(volHandler); sl@0: return result; sl@0: } sl@0: sl@0: return KErrNotSupported; sl@0: } sl@0: sl@0: void CA3fServerCiStubExtn::Release() sl@0: { sl@0: delete this; sl@0: } sl@0: sl@0: void CA3fServerCiStubExtn::PassDestructorKey(TUid aDestructorKey) sl@0: { sl@0: iKey = aDestructorKey; sl@0: } sl@0: sl@0: // CSetVol sl@0: sl@0: CSetVol* CSetVol::NewL(MCustomInterface& aCustomInterface) sl@0: { sl@0: CSetVol* self = new (ELeave) CSetVol(aCustomInterface); sl@0: CleanupStack::PushL(self); sl@0: self->ConstructL(); sl@0: CleanupStack::Pop(self); sl@0: return self; sl@0: } sl@0: sl@0: CSetVol::CSetVol(MCustomInterface& aCustomInterface): sl@0: iInterface(&aCustomInterface) sl@0: { sl@0: // do nothing sl@0: } sl@0: sl@0: void CSetVol::ConstructL() sl@0: { sl@0: iWait = new (ELeave) CActiveSchedulerWait(); sl@0: } sl@0: sl@0: CSetVol::~CSetVol() sl@0: { sl@0: delete iWait; sl@0: } sl@0: sl@0: TInt CSetVol::HandleMessageL(const RMmfIpcMessage& aMessage) sl@0: { sl@0: switch (aMessage.Function()) sl@0: { sl@0: case ETestSetVolIfSetVolCommand: sl@0: { sl@0: TPckgBuf<TInt> volPckg; sl@0: MmfMessageUtil::ReadL(aMessage, 1, volPckg); sl@0: UpdateA3fPointers(); // grab pointers to context, stream etc sl@0: SetVolumeL(volPckg()); sl@0: sl@0: User::LeaveIfError(iContext->RegisterAudioContextObserver(*this)); sl@0: sl@0: TInt error = iContext->Commit(); sl@0: if (!error) sl@0: { sl@0: iError = KErrNone; sl@0: iWait->Start(); sl@0: error = iError; sl@0: } sl@0: (void) iContext->UnregisterAudioContextObserver(*this); sl@0: sl@0: aMessage.Complete(error); sl@0: return KErrNone; // KErrNone says we've handled the message sl@0: } sl@0: case ETestSetVolIfVolCommand: sl@0: { sl@0: TPckgBuf<TInt> maxVolPckg; sl@0: MmfMessageUtil::ReadL(aMessage, 1, maxVolPckg); sl@0: UpdateA3fPointers(); // grab pointers to context, stream etc sl@0: TInt result = VolumeL(maxVolPckg()); sl@0: aMessage.Complete(result); sl@0: return KErrNone; // KErrNone says we've handled the message sl@0: } sl@0: default: sl@0: return KErrArgument; sl@0: } sl@0: } sl@0: sl@0: void CSetVol::UpdateA3fPointers() sl@0: { sl@0: MA3FBackdoorAccessIf* backdoor = sl@0: static_cast<MA3FBackdoorAccessIf*>(iInterface->CustomInterface(KA3FBackdoorAccessIfUid)); sl@0: if (backdoor) sl@0: { sl@0: iContext = backdoor->AudioContext(); sl@0: iStream = backdoor->AudioStream(); sl@0: iGain = backdoor->ProcessingUnit(KUidAudioGainControl); sl@0: } sl@0: else sl@0: { sl@0: iContext = NULL; sl@0: iStream = NULL; sl@0: iGain = NULL; sl@0: } sl@0: } sl@0: sl@0: void CSetVol::SetVolumeL(TInt aVolume) sl@0: { sl@0: RArray<TAudioChannelGain> channelGains; sl@0: CleanupClosePushL(channelGains); sl@0: TAudioChannelGain left; sl@0: TAudioChannelGain right; sl@0: left.iLocation = TAudioChannelGain::ELeft; sl@0: right.iLocation = TAudioChannelGain::ERight; sl@0: left.iGain = right.iGain = aVolume; sl@0: User::LeaveIfError(channelGains.Append(left)); // assumed element 0 in rest of code sl@0: User::LeaveIfError(channelGains.Append(right)); // assumed element 1 in rest of code sl@0: sl@0: MAudioGainControl* gainControl = static_cast<MAudioGainControl*>(iGain->Interface(KUidAudioGainControl)); sl@0: User::LeaveIfError(gainControl->SetGain(channelGains)); sl@0: CleanupStack::PopAndDestroy(&channelGains); sl@0: } sl@0: sl@0: TInt CSetVol::VolumeL(TInt aMaxVolume) sl@0: { sl@0: RArray<TAudioChannelGain> channelGains; sl@0: CleanupClosePushL(channelGains); sl@0: TInt maxGain; sl@0: sl@0: MAudioGainControl* gainControl = static_cast<MAudioGainControl*>(iGain->Interface(KUidAudioGainControl)); sl@0: User::LeaveIfError(gainControl->GetGain(channelGains)); sl@0: User::LeaveIfError(gainControl->GetMaxGain(maxGain)); sl@0: sl@0: TInt basicVolume = (channelGains[0].iGain + channelGains[1].iGain) / 2; sl@0: TInt result = basicVolume * aMaxVolume / maxGain; // scale to 0 to maxVolume sl@0: sl@0: CleanupStack::PopAndDestroy(&channelGains); sl@0: return result; sl@0: } sl@0: sl@0: void CSetVol::ContextEvent(TUid aEvent, TInt aError) sl@0: { sl@0: if (aEvent==KUidA3FContextUpdateComplete || aEvent==KUidA3FContextAbort) sl@0: { sl@0: // we are going to assume the SetGain() works and use the end of sl@0: // the ContextEvent. Really should observe the gain itself sl@0: if (aError) sl@0: { sl@0: iError = aError; sl@0: } sl@0: iWait->AsyncStop(); sl@0: } sl@0: } sl@0: sl@0: // sl@0: // ImplementationTable sl@0: // sl@0: sl@0: const TImplementationProxy ImplementationTable[] = sl@0: { sl@0: IMPLEMENTATION_PROXY_ENTRY(KUidA3fClientCiStubExtn, CA3fClientCiStubExtn::NewL), sl@0: IMPLEMENTATION_PROXY_ENTRY(KUidA3fServerCiStubExtn, CA3fServerCiStubExtn::NewL), sl@0: }; sl@0: sl@0: sl@0: // sl@0: // ImplementationGroupProxy sl@0: // sl@0: // sl@0: sl@0: EXPORT_C const TImplementationProxy* ImplementationGroupProxy(TInt& aTableCount) sl@0: { sl@0: aTableCount = sizeof(ImplementationTable) / sizeof(TImplementationProxy); sl@0: sl@0: return ImplementationTable; sl@0: } sl@0: sl@0: