mmserv/callaudiocontrol/src/CallAudioControlImpl.cpp
changeset 0 71ca22bcf22a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mmserv/callaudiocontrol/src/CallAudioControlImpl.cpp	Tue Feb 02 01:08:46 2010 +0200
@@ -0,0 +1,1138 @@
+/*
+* Copyright (c) 2007 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:  This is the implementation of the CCallAudioControlImpl class.
+*
+*/
+
+// INCLUDE FILES
+#include "CallAudioControlImpl.h"
+#include "CallAudioControlUtility.h"
+#include "CallAudioControlProperty.h"
+#include "CallAudioControlRepository.h"
+#include "CallAudioControlCommon.h"
+
+
+#ifdef __SERIES60_31__
+#include <features.hrh>
+#include <FeatMgr.h>
+#include <MediatorDomainUIDs.h>
+#include <e32property.h>
+#include <KPhEngConstants.h>
+_LIT(KPhoneCltExDllName, "PhoneClientExt.dll");
+#endif
+
+// -----------------------------------------------------------------------------
+// CCCallAudioControlImpl::NewL
+//
+// -----------------------------------------------------------------------------
+//
+CCallAudioControlImpl* CCallAudioControlImpl::NewL()
+    {
+    CCallAudioControlImpl* self = new (ELeave) CCallAudioControlImpl();
+    CleanupStack::PushL(self);
+    self->ConstructL();
+    CleanupStack::Pop(self);
+    return self;
+    }
+
+// -----------------------------------------------------------------------------
+// CCallAudioControlImpl::CCallAudioControlImpl
+// C++ constructor.
+// -----------------------------------------------------------------------------
+//
+CCallAudioControlImpl::CCallAudioControlImpl()
+    {
+    }
+
+// -----------------------------------------------------------------------------
+// CCallAudioControlImpl::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CCallAudioControlImpl::ConstructL()
+{
+	CAC_TRACE1(_L("CCallAudioControlImpl::ConstructL enter"));
+#ifdef __WINS__
+	iWinsTesting = ETrue;
+#endif
+	//Create objects for data base access (both Central Repository and Publish and Subscribe):
+	iCsNotifier = CCallAudioControlProperty::NewL(this, KUidCallInfo, KTelephonyCallState, ECallState );
+#ifdef __SERIES60_31__
+	CAC_TRACE1(_L("CCallAudioControlImpl::ConstructL Creating CMediatorCommandInitiator for 3.1 "));
+    iCommandInitiator = CMediatorCommandInitiator::NewL( this );
+    iMuteNotifier = CCallAudioControlProperty::NewL(this,KUidSystemCategory, KUidMute.iUid, EMute);
+#else
+    CAC_TRACE1(_L("CCallAudioControlImpl::ConstructL Creating CPhoneClient for non 3.1 "));
+    iPhoneClient = CPhCltCommandHandler::NewL();
+    iMuteNotifier = CCallAudioControlProperty::NewL(this,KUidMute, KTelephonyMute, EMute);
+#endif
+	iIhfVolumeNotifier = CCallAudioControlRepository::NewL(this,KUidVolume, KTelephonyIHFVolume, EIHFVolume);
+	iEpVolumeNotifier = CCallAudioControlRepository::NewL(this, KUidVolume, KTelephonyEPVolume, EEPVolume);
+    // Get current call state and is it active:
+    TBool active = IsCallActive();
+	CAC_TRACE2(_L("CCallAudioControl: Current Call State: %d"),iCallState);
+   	// If in active call create TAR, get current audio output routing and
+   	// get volume (based on audio routing) and set iVolume:
+	if (active)
+	{
+        CAC_TRACE1(_L("CCallAudioControl: Active Call: Setting iVolume, etc..."));
+		iTelephonyAudioRouting = CTelephonyAudioRouting::NewL(*this);
+		iCurrentAudioOutput = (CCallAudioControl::TAudioOutput)iTelephonyAudioRouting->Output();
+		TInt error = GetVolume();
+	}
+	else // Otherwise, get EP volume and set iVolume = EPVolume
+	{
+   		TInt error = iEpVolumeNotifier->Get(iVolume);
+   		CAC_TRACE2(_L("CCallAudioControl: Not active call, setting iVolume to EPVolume = %d"),iVolume);
+	}
+	// Subscribe for call state changes:
+	// if CAC is created before an active call, then we need to subscribe to Telephony notifications whenever the
+	// the call is active, so that CAC can create TAR for audio routing
+   	iCsNotifier->Subscribe();
+	CAC_TRACE1(_L("CCallAudioControlImpl::ConstructL exit"));
+}
+
+// -----------------------------------------------------------------------------
+// CCallAudioControlImpl::DestructL
+// Destructor
+// -----------------------------------------------------------------------------
+//
+CCallAudioControlImpl::~CCallAudioControlImpl()
+    {
+	CAC_TRACE2(_L("CCallAudioControlImpl[%x]::~AudioOutputControlImpl enter"),this);
+    // Empty arrays:
+    iRoutingObservers.Reset();
+    iDownlinkVolumeObservers.Reset();
+  	iUplinkGainObservers.Reset();
+	CAC_TRACE2(_L("~CAudioOutputControlImpl: Deleting Volume Notifiers..."),this);
+	delete iEpVolumeNotifier;
+	delete iIhfVolumeNotifier;
+	CAC_TRACE2(_L("~CAudioOutputControlImpl: Deleting Call State Notifier..."),this);
+	delete iCsNotifier;
+	CAC_TRACE2(_L("~CAudioOutputControlImpl: Deleting Mute Notifier..."),this);
+	delete iMuteNotifier;
+	CAC_TRACE2(_L("~CAudioOutputControlImpl: Deleting TAR..."),this);
+	delete iTelephonyAudioRouting;
+#ifdef __SERIES60_31__
+    CAC_TRACE2(_L("~CAudioOutputControlImpl: Deleting iCommandInitiator (3.1 ONLY)..."),this);
+    delete iCommandInitiator;
+#else
+	CAC_TRACE2(_L("~CAudioOutputControlImpl: Deleting iPhoneClient..."),this);
+	delete iPhoneClient;
+#endif
+
+
+	CAC_TRACE2(_L("CCallAudioControlImpl[%x]::~AudioOutputControlImpl exit"),this);
+
+    }
+
+// ---------------------------------------------------------
+// CCallAudioControlImpl::AppendRoutingObserver
+// ?implementation_description
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+TInt CCallAudioControlImpl::AppendRoutingObserver(CRoutingObserver& aObserver)
+    {
+	CAC_TRACE2(_L("CCallAudioControlImpl[%x]::AppendRoutingObserver enter"),this);
+	// Return with error if it's already in list:
+	for( TInt i = 0; i < iRoutingObservers.Count(); i++ )
+   	{
+        if ( iRoutingObservers[i] == &aObserver )
+       	{
+			CAC_TRACE1(_L("AppendRoutingObserver ERROR: Already Exists"));
+            return KErrAlreadyExists;
+      	}
+ 	}
+	iRoutingObservers.Append(&aObserver);
+	CAC_TRACE2(_L("CCallAudioControlImpl[%x]::AppendRoutingObserver exit"),this);
+	return KErrNone;
+
+    }
+
+// ---------------------------------------------------------
+// CCallAudioControlImpl::RemoveRoutingObserver
+// ?implementation_description
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+TInt CCallAudioControlImpl::RemoveRoutingObserver(CRoutingObserver& aObserver)
+    {
+	CAC_TRACE2(_L("CCallAudioControlImpl[%x]::RemoveRoutingObserver enter"),this);
+	TInt error(KErrNotFound);
+	for( TInt i = 0; i < iRoutingObservers.Count(); i++ )
+   	{
+        if ( iRoutingObservers[i] == &aObserver )
+       	{
+            iRoutingObservers.Remove(i);
+            error = KErrNone;
+            break;
+      	}
+ 	}
+	CAC_TRACE3(_L("CCallAudioControlImpl[%x]::RemoveRoutingObserver exit with error: %d"),this, error);
+	return error;
+
+    }
+
+// ---------------------------------------------------------
+// CCallAudioControlImpl::AppendDownlinkVolumeObserver
+// ?implementation_description
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+TInt CCallAudioControlImpl::AppendDownlinkVolumeObserver(CDownlinkVolumeObserver& aObserver)
+{
+	CAC_TRACE2(_L("CCallAudioControlImpl[%x]::AppendDownlinkVolumeObserver enter"),this);
+	// Return with error if it's already in list:
+	for( TInt i = 0; i < iDownlinkVolumeObservers.Count(); i++ )
+   	{
+        if ( iDownlinkVolumeObservers[i] == &aObserver )
+       	{
+			CAC_TRACE1(_L("AppendDownlinkVolumeObserver ERROR: Already Exists"));
+            return KErrAlreadyExists;
+      	}
+ 	}
+	iDownlinkVolumeObservers.Append(&aObserver);
+	CAC_TRACE2(_L("CCallAudioControlImpl[%x]::AppendDownlinkVolumeObserver exit"),this);
+	return KErrNone;
+
+}
+
+// ---------------------------------------------------------
+// CCallAudioControlImpl::RemoveDownlinkVolumeObserver
+// ?implementation_description
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+TInt CCallAudioControlImpl::RemoveDownlinkVolumeObserver(CDownlinkVolumeObserver& aObserver)
+    {
+	CAC_TRACE2(_L("CCallAudioControlImpl[%x]::RemoveDownlinkVolumeObserver enter"),this);
+	TInt error(KErrNotFound);
+	for( TInt i = 0; i < iDownlinkVolumeObservers.Count(); i++ )
+   	{
+        if ( iDownlinkVolumeObservers[i] == &aObserver )
+       	{
+            iDownlinkVolumeObservers.Remove(i);
+            error = KErrNone;
+      	}
+ 	}
+	CAC_TRACE3(_L("CCallAudioControlImpl[%x]::RemoveDownlinkVolumeObserver exit with error: %d"),this, error);
+	return error;
+    }
+
+// ---------------------------------------------------------
+// CCallAudioControlImpl::AppendUplinkGainObserver
+// ?implementation_description
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+TInt CCallAudioControlImpl::AppendUplinkGainObserver(CUplinkGainObserver& aObserver)
+    {
+	CAC_TRACE2(_L("CCallAudioControlImpl[%x]::AppendUplinkGainObserver enter"),this);
+	TInt error(KErrNone);
+	// Return with error if it's already in list:
+	for( TInt i = 0; i < iUplinkGainObservers.Count(); i++ )
+   	{
+        if ( iUplinkGainObservers[i] == &aObserver )
+       	{
+			CAC_TRACE1(_L("AppendUplinkGainObserver ERROR: Already Exists"));
+            return KErrAlreadyExists;
+      	}
+ 	}
+	error = iUplinkGainObservers.Append(&aObserver);
+    if (error == KErrNone)
+    {
+   		iMuteNotifier->Subscribe();
+    }
+	CAC_TRACE3(_L("CCallAudioControlImpl[%x]::AppendUplinkGainObserver Error [%d] exit"),this, error);
+    return error;
+    }
+
+// ---------------------------------------------------------
+// CCallAudioControlImpl::RemoveUplinkGainObserver
+// ?implementation_description
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+TInt CCallAudioControlImpl::RemoveUplinkGainObserver(CUplinkGainObserver& aObserver)
+{
+	CAC_TRACE2(_L("CCallAudioControlImpl[%x]RemoveUplinkGainObserver enter"),this);
+	TInt error(KErrNotFound);
+	for( TInt i = 0; i < iUplinkGainObservers.Count(); i++ )
+   	{
+        if ( iUplinkGainObservers[i] == &aObserver )
+       	{
+            iUplinkGainObservers.Remove(i);
+            error = KErrNone;
+      	}
+ 	}
+ 	// Unsubscribe for mute updates if list is empty and currently subscribed
+ 	if ( !iUplinkGainObservers.Count() )
+ 	{
+		iMuteNotifier->Unsubscribe();
+ 	}
+	CAC_TRACE3(_L("CCallAudioControlImpl[%x]::RemoveUplinkGainObserver exit with error: %d"),this, error);
+ 	return error;
+}
+
+// ---------------------------------------------------------
+// CCallAudioControlImpl::GetAvaliableOutputs
+// ?implementation_description
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+TInt CCallAudioControlImpl::GetAvailableOutputs(RArray<CCallAudioControl::TAudioOutput>& aAvailableOutputs)
+{
+	CAC_TRACE2(_L("CCallAudioControlImpl[%x]::GetAvailableOutputs enter"),this);
+    TInt error(KErrNone);
+    CCallAudioControl::TAudioOutput arrayElement;
+    TBool active = IsCallActive();
+   	if (active)
+    {
+    	if (!iTelephonyAudioRouting)
+    	{
+            CAC_TRACE1(_L("CCallAudioControlImpl[%x]::GetAvailableOutputs TAR not available "));
+            return KErrCompletion;
+    	}
+		TArray<CTelephonyAudioRouting::TAudioOutput> availableOutputArray = iTelephonyAudioRouting->AvailableOutputs();
+		TInt arrayCount = availableOutputArray.Count();
+ 		for (TInt i = 0; i < arrayCount; i++)
+  		{
+       		CAC_TRACE3(_L("AvailableOutput[%d] = %d"), i, availableOutputArray[i]);
+       		arrayElement = (CCallAudioControl::TAudioOutput)(availableOutputArray[i]);
+      		aAvailableOutputs.Append(arrayElement);
+   		}
+    }
+    else
+    	error = KErrPermissionDenied;
+	CAC_TRACE3(_L("CCallAudioControlImpl[%x]::GetAvailableOutputs exit with error: %d"),this, error);
+    return error;
+}
+
+// ---------------------------------------------------------
+// CCallAudioControlImpl::GetOutput
+// ?implementation_description
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+TInt CCallAudioControlImpl::GetOutput(CCallAudioControl::TAudioOutput& aOutput)
+{
+	CAC_TRACE2(_L("CCallAudioControlImpl[%x]::GetOutput enter"),this);
+	TInt error(KErrNone);
+    TBool active = IsCallActive();
+   	if (active)
+    {
+    	if (!iTelephonyAudioRouting)
+    	{
+            CAC_TRACE1(_L("CCallAudioControlImpl[%x]::GetOutput TAR not available "));
+            return KErrCompletion;
+    	}
+ 		aOutput = (CCallAudioControl::TAudioOutput)(iTelephonyAudioRouting->Output());
+ 		iCurrentAudioOutput = aOutput;
+		CAC_TRACE2(_L("GetOutput: Output retrieved: %d"),aOutput);
+    }
+    else
+    	error = KErrPermissionDenied;
+	CAC_TRACE3(_L("CCallAudioControlImpl[%x]::GetOutput exit with error: %d"),this, error);
+
+    return error;
+}
+
+// ---------------------------------------------------------
+// CCallAudioControlImpl::::SetOutput
+// ?implementation_description
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+TInt CCallAudioControlImpl::SetOutput(CCallAudioControl::TAudioOutput aOutput)
+{
+	CAC_TRACE3(_L("CCallAudioControlImpl[%x]::SetOutput with: %d"),this, aOutput);
+    TInt error(KErrNone);
+    TBool active = IsCallActive();
+   	if (active)
+    {
+    	if (!iTelephonyAudioRouting)
+    	{
+            CAC_TRACE1(_L("CCallAudioControlImpl[%x]::SetOutput TAR not available "));
+            return KErrCompletion;
+    	}
+
+    	if ((aOutput == CTelephonyAudioRouting::ENone) || (aOutput == CTelephonyAudioRouting::ENotActive))
+    	{
+    		return (KErrArgument);
+    	}
+		TRAP(error,iTelephonyAudioRouting->SetOutputL((CTelephonyAudioRouting::TAudioOutput)aOutput));
+    }
+    else
+    {
+		error = KErrPermissionDenied;
+    }
+	CAC_TRACE3(_L("CCallAudioControlImpl[%x]::SetOutput exit with error: %d"),this, error);
+    return error;
+}
+
+// ---------------------------------------------------------
+// CCallAudioControlImpl::::PreviousOutput
+// ?implementation_description
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+TInt CCallAudioControlImpl::PreviousOutput(CCallAudioControl::TAudioOutput& aPreviousOutput)
+{
+	CAC_TRACE2(_L("CCallAudioControlImpl[%x]::PreviousOutput enter"),this);
+    TInt error(KErrNone);
+    TBool active = IsCallActive();
+   	if (active)
+    {
+    	if (!iTelephonyAudioRouting)
+    	{
+            CAC_TRACE1(_L("CCallAudioControlImpl[%x]::PreviousOutput TAR not available "));
+            return KErrCompletion;
+    	}
+		aPreviousOutput = (CCallAudioControl::TAudioOutput)iTelephonyAudioRouting->PreviousOutput();
+    }
+    else
+    {
+    	error = KErrPermissionDenied;
+    }
+	CAC_TRACE3(_L("CCallAudioControlImpl[%x]::PreviousOutput exit with error: %d"),this, error);
+    return error;
+}
+
+// ---------------------------------------------------------
+// CCallAudioControlImpl::GetMinDownlinkVolume
+// ?implementation_description
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+TInt CCallAudioControlImpl::GetMinDownlinkVolume(TUint& aVolume)
+    {
+	CAC_TRACE2(_L("CCallAudioControlImpl[%x]::GetMinDownlinkVolume"),this);
+    // Hard-coded to 0:
+    aVolume = KMinVolume;
+    return KErrNone;
+    }
+
+// ---------------------------------------------------------
+// CCallAudioControlImpl::GetDownlinkVolume
+// ?implementation_description
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+TInt CCallAudioControlImpl::GetDownlinkVolume(TUint& aVolume)
+    {
+	CAC_TRACE3(_L("CCallAudioControlImpl[%x]::GetDownlinkVolume will return: iVolume"),this, iVolume);
+	TInt error(KErrNone);
+	if (iVolume < 0) // An error occurred while getting iVolume form DBase prior
+	{
+		error = iVolume; // return error to client
+	}
+	else
+	{
+    	aVolume = iVolume;
+	}
+    return error;
+    }
+
+// ---------------------------------------------------------
+// CCallAudioControlImpl::GetMaxDownlinkVolume
+// ?implementation_description
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+TInt CCallAudioControlImpl::GetMaxDownlinkVolume(TUint& aVolume)
+    {
+	CAC_TRACE2(_L("CCallAudioControlImpl[%x]::GetMaxDownlinkVolume"),this);
+    // Hard-coded to 10:
+    aVolume = KMaxVolume;
+    return KErrNone;
+    }
+
+// ---------------------------------------------------------
+// CCallAudioControlImpl::SetDownlinkVolume
+// ?implementation_description
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+TInt CCallAudioControlImpl::SetDownlinkVolume(TUint aVolume)
+    {
+	CAC_TRACE3(_L("CCallAudioControlImpl[%x]::SetDownlinkVolume to: %d"),this, aVolume);
+	TInt newVolume = 0;
+    // Verify OK to set volume, which is only allowed during an
+    // active call and if audio routing is appropriate:
+    TInt error = CheckIfOkToSetVolume();
+    if (error != KErrNone)
+    {
+	CAC_TRACE2(_L("SetDownlinkVolume: ERROR: %d"), error);
+   	return error;
+    }
+    // Make sure aVolume range is valid and set newVolume:
+    newVolume = VerifyAndSetVolume(aVolume);
+    TUint currVol;
+    RETURN_IF_ERROR(GetDownlinkVolume(currVol));
+    if (currVol !=  aVolume)
+        {
+        // Update correct volume key, based on current audio routing:
+        if ( (iCurrentAudioOutput == CTelephonyAudioRouting::EHandset) || (iCurrentAudioOutput == CTelephonyAudioRouting::EWiredAudioAccessory))
+        {
+            error = iEpVolumeNotifier->Set(newVolume);
+            iPendingEpVolLevelOp = ETrue;
+            iRequestedEpVolLevel = aVolume;
+        }
+        else if (iCurrentAudioOutput == CTelephonyAudioRouting::ELoudspeaker)
+        {
+            error = iIhfVolumeNotifier->Set(newVolume);
+            iPendingIhfVolLevelOp = ETrue;
+            iRequestedIhfVolLevel = aVolume;
+        }
+        else
+            error = KErrArgument; // invalid iCurrentAudioOutput value
+        }
+	CAC_TRACE3(_L("CCallAudioControlImpl[%x]::SetDownlinkVolume exit with error: %d"),this, error);
+    return error;
+
+    }
+
+// ---------------------------------------------------------
+// CCallAudioControlImpl::GetUplinkMute
+// ?implementation_description
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+TInt CCallAudioControlImpl::GetUplinkMute(TBool& aMute)
+{
+	CAC_TRACE2(_L("CCallAudioControlImpl[%x]::GetUplinkMute enter"),this);
+   	TInt error = iMuteNotifier->Get(aMute);
+   	RETURN_IF_ERROR(error);
+#ifdef __SERIES60_31__
+    if (aMute == EPSMicMuteOn)
+        aMute = ETrue;
+    else if ((aMute == EPSMicMuteOff) || (aMute == EPSMicMuteStateUninitialized))
+        aMute = EFalse;
+    else
+        error = KErrUnknown;
+#else
+    /* 3.2 and beyond: */
+    /* 3.2 also appears to be an enum defined in s60/app/telephony/inc/KPhEngConstants.h
+     * Check with component owner */
+    #ifndef __SERIES60_32__ /* 5.0 and beyond */
+        if (aMute == EPSTelMicMuteOn)
+            aMute = ETrue;
+        else if ((aMute == EPSTelMicMuteOff) || (aMute == EPSTelMicMuteStateUninitialized))
+            aMute = EFalse;
+        else
+            error = KErrUnknown;
+    #endif /*#ifndef __SERIES60_32__*/
+#endif /*#ifdef __SERIES60_31__*/
+
+	CAC_TRACE2(_L("GetUplinkMute: aMute: %d"),aMute);
+	CAC_TRACE3(_L("CCallAudioControlImpl[%x]::GetUplinkMute exit with error: %d"),this, error);
+	return error;
+}
+
+// ---------------------------------------------------------
+// CCallAudioControlImpl::SetUplinkMute
+// ?implementation_description
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+TInt CCallAudioControlImpl::SetUplinkMute(TBool aMute)
+    {
+	CAC_TRACE3(_L("CCallAudioControlImpl[%x]::SetUplinkMute with %d"),this, aMute);
+	// Set only if active call:
+    TInt error(KErrNone);
+    TBool active = IsCallActive();
+	if (active)
+	{
+		if (iWinsTesting)
+		{
+			error = KErrPermissionDenied;
+		}
+		else
+		{
+		TBool curMuteState;
+		RETURN_IF_ERROR(GetUplinkMute(curMuteState));
+		if (aMute != curMuteState)
+		    {
+            error = SetMute(aMute); // Mute audio
+            iPendingMuteSetOp = ETrue;
+            iRequestedMuteState = aMute;
+		    }
+		}
+	}
+	else
+	{
+		error = KErrPermissionDenied;
+	}
+	CAC_TRACE3(_L("CCallAudioControlImpl[%x]::SetUplinkMute exit with error: %d"),this, error);
+    return error;
+    }
+
+// ---------------------------------------------------------
+// CCallAudioControlImpl::SetMute
+// ?implementation_description
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+TInt CCallAudioControlImpl::SetMute(TBool aMute)
+    {
+	CAC_TRACE3(_L("CCallAudioControlImpl[%x]::SetMute Enter with %d"),this, aMute);
+	TInt error(KErrNone);
+#ifdef __SERIES60_31__
+	TBool coverUIPresent = EFalse;
+    FeatureManager::InitializeLibL();
+    coverUIPresent = FeatureManager::FeatureSupported( KFeatureIdCoverDisplay );
+    FeatureManager::UnInitializeLib();
+	if ( coverUIPresent )
+	    {
+        TSESetMicrophonePckg pckg(aMute);
+	    error = iCommandInitiator->IssueCommand( KMediatorSecondaryDisplayDomain,
+	            KTSECategory, ECmdMuteOrUnmuteMicrophone, TVersion( KVersioMajor, KVersioMinor, KVersioBuild ), pckg );
+	    }
+	else
+	    {
+        TRequestStatus status;
+        TInt libEntry;
+        // In S60 3.1 CPhCltCommandHandler cannot be directly used. From 3.2 onwards it can be used directly.
+        CPhCltExtFactory* phCltExtFactory = NULL;
+        CPhCltCommandHandler* phCommandHandler = NULL;
+        User::LeaveIfError( iPhoneClientServer.Connect() );
+        User::LeaveIfError( iLibrary.Load( KPhoneCltExDllName ) );
+        libEntry = iLibrary.Lookup(1)();
+        phCltExtFactory = reinterpret_cast<CPhCltExtFactory*>( libEntry );
+        if (phCltExtFactory)
+            {
+            phCommandHandler = phCltExtFactory->CPhCltCommandHandlerLD();
+            User::LeaveIfError( phCommandHandler->Open( iPhoneClientServer ) );
+            if (aMute)
+                {
+                phCommandHandler->MuteMicrophone(status, ETrue);
+                }
+            else
+                {
+                phCommandHandler->MuteMicrophone(status, EFalse);
+                }
+            User::WaitForRequest( status );
+            if (status.Int() != KErrNone)
+                {
+                error = KErrGeneral;
+                }
+            }
+        phCommandHandler = NULL;
+        phCltExtFactory = NULL;
+        iLibrary.Close();
+        iPhoneClientServer.Close();
+	    }
+#else
+	TRequestStatus status;
+	if (aMute)
+		iPhoneClient->MuteMicrophone(status, ETrue);
+	else
+		iPhoneClient->MuteMicrophone(status, EFalse);
+	User::WaitForRequest( status );
+	if (status.Int() != KErrNone)
+	{
+		CAC_TRACE2(_L("SetMute: ERROR from PhoneClient->MuteMic: %d"),status.Int());
+		error = KErrGeneral;
+	}
+#endif /*#ifdef __SERIES60_31__*/
+	CAC_TRACE3(_L("CCallAudioControlImpl[%x]::SetMute exit with error: %d"),this, error);
+    return error;
+    }
+// ---------------------------------------------------------
+// CCallAudioControlImpl::GetVolume
+// ?implementation_description
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+TInt CCallAudioControlImpl::GetVolume()
+ {
+	CAC_TRACE2(_L("CCallAudioControlImpl[%x]::GetVolume enter"),this);
+	CAC_TRACE2(_L("GetVolume: current audio output = %d"),iCurrentAudioOutput);
+	TInt error(KErrNone);
+	switch (iCurrentAudioOutput)
+	{
+		case CTelephonyAudioRouting::ENotActive:
+		case CTelephonyAudioRouting::ENone:
+        case CTelephonyAudioRouting::EBTAudioAccessory:
+		case CTelephonyAudioRouting::ETTY:
+			CAC_TRACE1(_L("GetVolume: Audio Routing = Not Active, None, BT or TTY. iVolume set to -19"));
+			iVolume = KErrUnknown;
+			iEpVolumeNotifier->NotifyCancel();
+			iIhfVolumeNotifier->NotifyCancel();
+			break;
+		case CTelephonyAudioRouting::EHandset:
+		case CTelephonyAudioRouting::EWiredAudioAccessory:
+		    // iVolume = EP Volume, cancel IHF subscription, subscribe to EP
+			CAC_TRACE1(_L("GetVolume: Audio Routing = Handset or Wired accessory: Get EPVolume"));
+   			error = iEpVolumeNotifier->Get(iVolume);
+   			if (error != KErrNone)
+   			{
+				CAC_TRACE2(_L("GetVolume: Error returned from EP Volume Get: %d"),error);
+   			}
+			iIhfVolumeNotifier->NotifyCancel();
+			iEpVolumeNotifier->NotifyRequest();
+			break;
+		case CTelephonyAudioRouting::ELoudspeaker:
+			// iVolume = IHF volume, cancel EP subscription, subscribe to IHF
+			CAC_TRACE1(_L("GetVolume: Audio Routing = Loudspeaker: Get IHF Volume"));
+   			error = iIhfVolumeNotifier->Get( iVolume );
+   			if (error != KErrNone)
+   			{
+				CAC_TRACE2(_L("GetVolume: Error returned from IHFVolume Get: %d"),error);
+   			}
+			iEpVolumeNotifier->NotifyCancel();
+			iIhfVolumeNotifier->NotifyRequest();
+			break;
+		default:
+			break;
+	} // End Switch
+
+	if (error != KErrNone) // Set iVolume to error code in case there was an error getting it
+	{
+		CAC_TRACE2(_L("GetVolume: ERROR, so iVolume = error = %d"), error);
+		iVolume = error;
+	}
+	CAC_TRACE4(_L("CCallAudioControlImpl[%x]::GetVolume exit with error: %d, and iVolume = %d"),this, error, iVolume);
+	return error;
+}
+
+// ---------------------------------------------------------
+// CCallAudioControlImpl::CheckIfOkToSetVolume
+// ?implementation_description
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+TInt CCallAudioControlImpl::CheckIfOkToSetVolume()
+{
+	CAC_TRACE2(_L("CCallAudioControlImpl[%x]::CheckIfOkToSetVolume enter"),this);
+	// if WINS, it's ok to set volume:
+	if (iWinsTesting)
+		return KErrNone;
+    TBool active = IsCallActive();
+	if (!active)
+	{
+		CAC_TRACE2(_L("CheckIfOkToSetVolume NOT OK, Not active call. iCallState: %d"), iCallState);
+		return KErrPermissionDenied;
+	}
+	// IF device is BT/TTY/ENone/EActive return KErrNotSupported:
+	if ((iCurrentAudioOutput == CTelephonyAudioRouting::ENotActive) ||
+	    (iCurrentAudioOutput == CTelephonyAudioRouting::ENone) ||
+	    (iCurrentAudioOutput == CTelephonyAudioRouting::EBTAudioAccessory) ||
+	    (iCurrentAudioOutput == CTelephonyAudioRouting::ETTY) )
+	{
+		CAC_TRACE2(_L("CheckIfOkToSetVolume NOT OK, Audio Output: %d"), iCurrentAudioOutput);
+		return KErrNotSupported;
+	}
+	CAC_TRACE2(_L("CCallAudioControlImpl[%x]::CheckIfOkToSetVolume exit"),this);
+	return KErrNone;
+}
+
+// ---------------------------------------------------------
+// CCallAudioControlImpl::VerifyAndSetVolume
+// ?implementation_description
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+TInt CCallAudioControlImpl::VerifyAndSetVolume(TInt aVolume)
+    {
+	CAC_TRACE3(_L("CCallAudioControlImpl[%x]::VerifyAndSetVolume for: %d "),this, aVolume);
+	TInt newVolume;
+	if (aVolume > KMaxVolume)
+		newVolume = KMaxVolume;
+	else if (aVolume < KMinVolume)
+		newVolume = KMinVolume;
+	else
+		newVolume = aVolume;
+	CAC_TRACE3(_L("CCallAudioControlImpl[%x]::VerifyAndSetVolume: newVolume = %d "),this, newVolume);
+	return newVolume;
+    }
+
+// ---------------------------------------------------------
+// CCallAudioControlImpl::HandleCallStateChange
+// ?implementation_description
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+TInt CCallAudioControlImpl::HandleCallStateChange()
+{
+	CAC_TRACE2(_L("CCallAudioControlImpl[%x]::HandleCallStateChange enter"), this);
+	TInt error(KErrNone);
+    TBool active = IsCallActive();
+	if (active ) // Active call or WINS
+	{
+		if (!iTelephonyAudioRouting)
+		{
+			TRAP(error,iTelephonyAudioRouting = CTelephonyAudioRouting::NewL(*this));
+			if (error != KErrNone)
+				return error;
+		}
+		iCurrentAudioOutput = (CCallAudioControl::TAudioOutput)iTelephonyAudioRouting->Output();
+		error = GetVolume();
+		if (error != KErrNone)
+		{
+			CAC_TRACE2(_L("HandleCallStateChange: Error trying to get Volume: %d "), error);
+			return error;
+		}
+	} // end if
+    else // Not active, delete TAR if it exists, and set iVolume = EPVolume
+    {
+    	if (iTelephonyAudioRouting)
+    	{
+    		delete iTelephonyAudioRouting;
+    		iTelephonyAudioRouting = NULL;
+    	}
+    	error = iEpVolumeNotifier->Get(iVolume);
+		if (error != KErrNone)
+		{
+			CAC_TRACE2(_L("HandleCallStateChange: Error trying to get EPVolume: %d "), error);
+			iVolume = error; // set iVolume with error code instead of dBase garbage
+		}
+    } // end else
+	CAC_TRACE3(_L("CCallAudioControlImpl[%x]::HandleCallStateChange exit with error: %d"), this, error);
+    return error;
+}
+
+// ---------------------------------------------------------
+// CCallAudioControlImpl::HandleEPVolumeChange
+// ?implementation_description
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+TInt CCallAudioControlImpl::HandleEPVolumeChange(TInt aVolume)
+    {
+	CAC_TRACE3(_L("CCallAudioControlImpl[%x]::HandleEPVolumeChange for: %d"),this, aVolume);
+	TInt error(KErrPermissionDenied);
+	// Ignore volume update unless active call and routing is earpiece or wired accessory:
+    TBool active = IsCallActive();
+	if (active)
+	{
+		error = KErrNone;
+		if ((iCurrentAudioOutput == CTelephonyAudioRouting::EHandset) || (iCurrentAudioOutput == CTelephonyAudioRouting::EWiredAudioAccessory) )
+		{
+        if (iPendingEpVolLevelOp && (iRequestedEpVolLevel == aVolume))
+            {
+            return error;
+            }
+        else
+            {
+            iPendingEpVolLevelOp = EFalse;
+            iVolume = aVolume;
+            //Notify clients:
+            NotifyVolumeObservers();
+			}
+		}
+	}
+	return error;
+    }
+
+// ---------------------------------------------------------
+// CCallAudioControlImpl::HandleIHFVolumeChange
+// ?implementation_description
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+TInt CCallAudioControlImpl::HandleIHFVolumeChange(TInt aVolume)
+    {
+	CAC_TRACE3(_L("CCallAudioControlImpl[%x]::HandleIHFVolumeChange for: %d "),this, aVolume);
+	TInt error(KErrPermissionDenied);
+	// Ignore volume update unless active call and routing is Loudspeaker:
+    TBool active = IsCallActive();
+	if (active)
+	{
+		error = KErrNone;
+		if (iCurrentAudioOutput == CTelephonyAudioRouting::ELoudspeaker)
+		{
+        if (iPendingIhfVolLevelOp && (iRequestedIhfVolLevel == aVolume))
+            {
+            return error;
+            }
+        else
+            {
+            iPendingIhfVolLevelOp = EFalse;
+            iVolume = aVolume;
+            //Notify clients:
+            NotifyVolumeObservers();
+            }
+		}
+	}
+	return error;
+    }
+
+// ---------------------------------------------------------
+// CCallAudioControlImpl::HandleMuteChange
+// ?implementation_description
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+TInt CCallAudioControlImpl::HandleMuteChange(TBool aMute)
+    {
+	CAC_TRACE3(_L("CCallAudioControlImpl[%x]::HandleMuteChange for: %d "),this, aMute);
+	TInt error(KErrPermissionDenied);
+    TBool active = IsCallActive();
+	// Ignore mute update unless active call and mute state has changed
+	if (active)
+	{
+		error = KErrNone;
+        if (iPendingMuteSetOp &&
+                ( iRequestedMuteState == aMute))
+            {
+            return error;
+            }
+        else
+            {
+            iPendingMuteSetOp = EFalse;
+			//Notify clients:
+			NotifyGainObservers();
+            }
+	}
+	return error;
+    }
+
+// ---------------------------------------------------------
+// CCallAudioControlImpl::NotifyVolumeObservers
+// ?implementation_description
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void CCallAudioControlImpl::NotifyVolumeObservers()
+{
+	CAC_TRACE2(_L("CCallAudioControlImpl[%x]::NotifyVolumeObservers "),this);
+	for( TInt i = 0; i < iDownlinkVolumeObservers.Count(); i++ )
+   	{
+		CAC_TRACE2(_L("NotifyVolumeObservers[%d] "), i);
+    	iDownlinkVolumeObservers[i]->DownlinkVolumeEvent(*(CCallAudioControl*)this, CDownlinkVolumeObserver::KDownlinkVolumeChanged);
+ 	}
+}
+
+// ---------------------------------------------------------
+// CCallAudioControlImpl::NotifyGainObservers
+// ?implementation_description
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void CCallAudioControlImpl::NotifyGainObservers()
+{
+	CAC_TRACE2(_L("CCallAudioControlImpl[%x]::NotifyGainObservers "),this);
+	for( TInt i = 0; i < iUplinkGainObservers.Count(); i++ )
+   	{
+		CAC_TRACE2(_L("NotifyGainObservers[%d] "), i);
+    	iUplinkGainObservers[i]->UplinkGainEvent(*(CCallAudioControl*)this, CUplinkGainObserver::KUplinkMuteStateChanged);
+ 	}
+}
+
+// ---------------------------------------------------------
+// CCallAudioControlImpl::NotifyRoutingObservers
+// ?implementation_description
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void CCallAudioControlImpl::NotifyRoutingObservers(TUint aEvent, TInt aError)
+{
+	CAC_TRACE2(_L("CCallAudioControlImpl[%x]::NotifyRoutingObservers "),this);
+	for( TInt i = 0; i < iRoutingObservers.Count(); i++ )
+   	{
+		CAC_TRACE2(_L("NotifyRoutingObservers[%d] "), i);
+    	iRoutingObservers[i]->RoutingEvent(*(CCallAudioControl*)this, aEvent, aError);
+ 	}
+}
+
+// ---------------------------------------------------------
+// CCallAudioControlImpl::NotifyRoutingObservers
+// ?implementation_description
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void CCallAudioControlImpl::NotifyRoutingObservers(TUint aEvent)
+{
+	CAC_TRACE2(_L("CCallAudioControlImpl[%x]::NotifyRoutingObservers "),this);
+	for( TInt i = 0; i < iRoutingObservers.Count(); i++ )
+   	{
+		CAC_TRACE2(_L("NotifyRoutingObservers[%d] "), i);
+    	iRoutingObservers[i]->RoutingEvent(*(CCallAudioControl*)this, aEvent);
+ 	}
+}
+
+// -----------------------------------------------------------------------------
+// CCallAudioControlImpl::AvailableOutputsChanged
+// The following methods are required for MTelephonyAudioRoutingObserver
+// -----------------------------------------------------------------------------
+//
+void CCallAudioControlImpl::AvailableOutputsChanged( CTelephonyAudioRouting& /*aTelephonyAudioRouting*/)
+{
+	CAC_TRACE1(_L("CCallAudioControlImpl::AvailableOutputsChanged"));
+	// ignore callback unless this condition is true
+    TBool active = IsCallActive();
+	if (active)
+    {
+    	// Perform AvailableOutputsChanged callback to all existing CRoutingObservers:
+    	NotifyRoutingObservers(CRoutingObserver::KAvailableOutputsChanged);
+    }
+}
+
+// -----------------------------------------------------------------------------
+// CCallAudioControlImpl::OutputChanged
+// -----------------------------------------------------------------------------
+//
+  void CCallAudioControlImpl::OutputChanged( CTelephonyAudioRouting& aTelephonyAudioRouting)
+  {
+  	CAC_TRACE1(_L("CCallAudioControlImpl[%x]::OutputChanged Enter"));
+	// Get and save previous and current audio output values:
+   	iCurrentAudioOutput = (CCallAudioControl::TAudioOutput)aTelephonyAudioRouting.Output();
+   	iPreviousAudioOutput = (CCallAudioControl::TAudioOutput)aTelephonyAudioRouting.PreviousOutput();
+	// ignore callback unless this condition is true
+    TBool active = IsCallActive();
+	if (active)
+    {
+     	TInt tempVol = iVolume; // save off iVolume
+    	// get volume from keys, based on new audio output, and set iVolume:
+    	GetVolume();
+    	// Perform OutputChanged callback to all existing CRoutingObservers:
+    	NotifyRoutingObservers(CRoutingObserver::KOutputChanged);
+    	// If there's a volume change, notify all existing CDownlinkVolumeObservers:
+    	if (tempVol != iVolume)
+    	{
+    		NotifyVolumeObservers();
+    	}
+    }
+  	CAC_TRACE1(_L("CCallAudioControlImpl::OutputChanged Exit"));
+  }
+
+// -----------------------------------------------------------------------------
+// CCallAudioControlImpl::SetOutputComplete
+// -----------------------------------------------------------------------------
+//
+  void CCallAudioControlImpl::SetOutputComplete( CTelephonyAudioRouting& aTelephonyAudioRouting, TInt aErr)
+  {
+
+  	CAC_TRACE3(_L("CCallAudioControlImpl[%x]::SetOutputComplete With Error Code: %d"), this, aErr);
+   	iCurrentAudioOutput = (CCallAudioControl::TAudioOutput)aTelephonyAudioRouting.Output();
+   	iPreviousAudioOutput = (CCallAudioControl::TAudioOutput)aTelephonyAudioRouting.PreviousOutput();
+	// ignore callback unless this condition is true
+   	TBool active = IsCallActive();
+	if (active)
+    {
+    	TInt tempVol = iVolume; // save off iVolume
+    	// get volume from keys, based on new audio output, and set iVolume:
+    	GetVolume();
+    	// Perform OutputChanged callback to all existing CRoutingObservers:
+    	NotifyRoutingObservers(CRoutingObserver::KSetOutputComplete, aErr);
+    	// If there's a volume change, notify all existing CDownlinkVolumeObservers:
+    	if (tempVol != iVolume)
+    	{
+    		NotifyVolumeObservers();
+    	}
+    }
+  }
+
+// -----------------------------------------------------------------------------
+// CCallAudioControlImpl::NotifyL
+// -----------------------------------------------------------------------------
+//
+void CCallAudioControlImpl::NotifyL(TAction aAction, TInt aError, TInt aValue)
+    {
+    CAC_TRACE5(_L("CCallAudioControlImpl[%x]::NotifyL for Action: %d, Error: %d and Value: %d"),this, aAction, aError, aValue);
+    switch (aAction)
+        {
+        case ECallState: // Call state change notification
+            {
+            CAC_TRACE1(_L("NotifyL: Call State Change Notification"));
+            iCallState = aValue;
+            HandleCallStateChange();
+            }
+            break;
+        case EEPVolume: // EP Volume change notification
+            {
+            CAC_TRACE1(_L("NotifyL: EP VOlume Change Notification"));
+            TInt tempVol = aValue;
+            HandleEPVolumeChange(tempVol);
+            }
+            break;
+        case EIHFVolume: // Handle IHF volume change Notification
+            {
+            CAC_TRACE1(_L("NotifyL: IHF Volume Change Notification"));
+            TInt tempVol = aValue;
+            HandleIHFVolumeChange(tempVol);
+            }
+            break;
+
+        case EMute: // Handle mute change Notification
+            {
+            CAC_TRACE1(_L("NotifyL: Uplink Mute Change Notification"));
+            TBool tempMute = aValue;
+#ifdef __SERIES60_31__
+            if (aValue == EPSMicMuteOn)
+                tempMute = ETrue;
+            else
+                tempMute = EFalse;
+#endif
+            HandleMuteChange(tempMute);
+            }
+            break;
+        default:
+            CAC_TRACE1(_L("NotifyL: UNKNOWN Notification"));
+            break;
+        } // End switch
+    }
+
+// -----------------------------------------------------------------------------
+// CCallAudioControlImpl::CommandResponseL
+//
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+#ifdef __SERIES60_31__
+void CCallAudioControlImpl::CommandResponseL( TUid /*aKMediatorSecondaryDisplayDomain*/,
+						TUid /*aKTSECategory*/,
+                        TInt aCommandId,
+                        TInt aStatus,
+                        const TDesC8& /*aData*/ )
+     {
+	CAC_TRACE2(_L("CCallAudioControlImpl[%x]::CommandResponseL "),this);
+     if ( aStatus != KErrNone)
+         {
+         CAC_TRACE2(_L("CommandResponseL: Command error [%d] "), aStatus);
+         }
+     else
+         {
+         switch ( aCommandId )
+             {
+             case ECmdMuteOrUnmuteMicrophone:
+		        CAC_TRACE1(_L("CommandResponseL: Mute Unmute microphone succeeded "));
+                break;
+            default:
+                CAC_TRACE1(_L("CommandResponseL: ERROR: Unknown Command Response Received"));
+                break;
+             }
+         } // End else
+     }
+#endif
+
+// -----------------------------------------------------------------------------
+//
+//
+//
+// -----------------------------------------------------------------------------
+//
+TBool CCallAudioControlImpl::IsCallActive()
+{
+	CAC_TRACE1(_L("CCallAudioControlImpl::IsCallActive"));
+	iCsNotifier->Get(iCallState);
+	if ((iCallState == ECallStateConnected) || (iCallState == ECallStateHold) || iWinsTesting )
+    {
+		return ETrue;
+    }
+	return EFalse;
+}
+// End of file