// Copyright (c) 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 "cdevcommoncontrol.h"
#include <a3f/maudiocontext.h> 
#include <a3f/maudiocodec.h>


CDevCommonControl::CDevCommonControl()
    {
    TRACE_CREATE();
    DP_CONTEXT(CDevCommonControl::CDevCommonControl, CtxDevSound, DPLOCAL);
    DP_IN();
    DP_OUT();
    }


CDevCommonControl::~CDevCommonControl()
    {
    DP_CONTEXT(CDevCommonControl::~CDevCommonControl, CtxDevSound, DPLOCAL);
    DP_IN();
    DP_OUT();
    }


TInt CDevCommonControl::Stop() // from CDevAudioControl
    {
    DP_CONTEXT(CDevCommonControl::Stop, CtxDevSound, DPLOCAL);
    DP_IN();

    TInt err = KErrNone;
    switch(iDevAudio->iActiveState)
        {
        case EDevSoundAdaptorActive_Active:
        case EDevSoundAdaptorPaused_Primed:
            err = iDevAudio->iAudioStream->Stop();
            if (err == KErrNone)
                {
                err = iDevAudio->CommitAudioContext();
                }
            if (err == KErrNone)
                {
                iDevAudio->iActiveState = EDevSoundAdaptorStopping;
                }
            break;
        case EDevSoundAdaptorGoingActive:
            iDevAudio->iActiveState = EDevSoundAdaptorStopping;
            break;
        case EDevSoundAdaptorInitialised_Idle:
        	{
        	//If following condition is true, then we are here because of a
        	//pre-emption clash in last Commit cycle started from
        	//CDevCommonControl::ContextEventUpdateWithStateEventNoError.
        	if(iDevAudio->iPreviousState == EDevSoundAdaptorUnloading)
        		{
				err = Unload();
				break;
        		}
        	}
        default:
            break;
        }
    
    if(err == KErrNone)
        {
        iDevAudio->iStop = ETrue;
        }
    
    DP0_RET(err,"%d");
    }


TInt CDevCommonControl::Pause() // from CDevAudioControl
    {
    DP_CONTEXT(CDevCommonControl::Pause, CtxDevSound, DPLOCAL);
    DP_IN();

    TInt err = iDevAudio->iAudioStream->Prime();
    if ( err == KErrNone)
        {
        err = iDevAudio->CommitAudioContext();
        }
    if (err == KErrNone)
        {
        iDevAudio->iActiveState = EDevSoundAdaptorPausing;
        }
    
    DP0_RET(err,"%d");
    }


TInt CDevCommonControl::Resume() // from CDevAudioControl
    {
    DP_CONTEXT(CDevCommonControl::Resume, CtxDevSound, DPLOCAL);
    DP_IN();
    
    TInt err = KErrNone;
    if(iDevAudio->iActiveState != EDevSoundAdaptorPaused_Primed)
        {
        err = KErrNotReady;
        }

    //If following condition is true, then we are here because of a
    //pre-emption clash in last Commit cycle started from
    //CDevCommonControl::ContextEventUpdateWithStateEventAndError.
    if(iDevAudio->iActiveState == EDevSoundAdaptorInitialised_Idle &&
    		iDevAudio->iPreviousState == EDevSoundAdaptorUnloading)
    	{
		err = Unload();
		DP0_RET(err,"%d");
    	}

    if(err == KErrNone)
        {
        // Populate gain and balance values set in the Paused state and being cached
        err = iDevAudio->RequestGainAndBalance(this);
        }
    if(err == KErrNone)
        {
        err = iDevAudio->iAudioStream->Activate();
        }
    if ( err == KErrNone)
        {
        err = iDevAudio->CommitAudioContext();
        }
    if (err == KErrNone)
        {
        iDevAudio->iActiveState = EDevSoundAdaptorActivating;
        }
    
    DP0_RET(err,"%d");
    }


void CDevCommonControl::StateEvent(MAudioStream& aStream, TInt aError,  // from MAudioProcessingUnitObserver
                                    TAudioState aNewState)
    {
    DP_CONTEXT(CDevCommonControl::StateEvent, CtxDevSound, DPLOCAL);
    DP3_IN("activeState %d -> newstate %d, (%d)",
            iDevAudio->iActiveState, aNewState, aError);
    
    __ASSERT_ALWAYS(iDevAudio->iAudioStream == &aStream, Panic(EStreamMismatch));
    
    if(aError != KErrNone || iDevAudio->iActiveStreamState != aNewState) 
        {
        iDevAudio->iActiveStreamState = aNewState;
        iStateEventReceived = ETrue;
        }
    // Since the audiostream already demoted the state for the most of the cases
    // only is need  when a error comes were the stream was at the middle of A3f two-phase transition
    else
        {
        switch (aNewState)
            {
            case EIdle:
                // Demote the stream state
                iDevAudio->iActiveStreamState = EIdle;
                break;
            default:
                break;
            }
        }
    iStateEventError = aError;
    
    DP_OUT();
    }


void CDevCommonControl::ProcessingUnitError(MAudioProcessingUnit* /*aInstance*/, // from MAudioProcessingUnitObserver
                                                                 TInt aError)
    {
    DP_CONTEXT(CDevCommonControl::ProcessingUnitError, CtxDevSound, DPLOCAL);
    DP_IN();

    if(iCallbackFromAdaptor == KCallbackNone)   
        {
        iProcessingUnitError = aError;
        iCallbackFromAdaptor = KCallbackProcessingUnitError;
        iAdaptationObserver->CallbackFromAdaptorReceived(KCallbackProcessingUnitError, aError);
        }
    else
        {
        // Multiple callbacks from adaptor
        DP0(DLINFO, "Multiple callbacks from adaptor");
        }
    
    DP_OUT();
    }


void CDevCommonControl::ContextEvent(TUid aEvent, TInt aError) 
    {
    DP_CONTEXT(CDevCommonControl::ContextEvent, CtxDevSound, DPLOCAL);
    DP3_IN("ContextEvent aEvent=%x iActiveState=%d aError=%d",aEvent, iDevAudio->iActiveState, aError);

    // Can't "switch {...}" on UIDs unfortunately:
    if (aEvent == KUidA3FContextUpdateComplete)
        {
        if(iBeingPreempted)
            {
			if(iStateEventReceived)
				{
				//use a sub state pattern to make pre-emption cycles like other cycles.
				DP1(DLERR,"Preemption error=%d", aError);
				iDevAudio->iActiveState = EDevSoundAdaptorBeingPreempted;
				if(iPreemptionClash)
					{
					// remove last request from front of queue without processing it
					iAdaptationObserver->PreemptionClashWithStateChange();
					iPreemptionClash=EFalse;
					}
				}
            else if(!iStateEventReceived && iPreemptionClash)
        		{
				iIgnoreAsyncOpComplete=ETrue;
				iPreemptionClash=EFalse;
        		}
			iBeingPreempted=EFalse;
            }
		ContextEventUpdateComplete(aError);
        }

    else if ((aEvent == KUidA3FContextCommitUpdate))
        {
        iBeingPreempted=EFalse; // clear being preempted
        iPreemptionClash=EFalse; // clear pre-emption clash flag
        TBool adaptorControlsContext = iAdaptationObserver->AdaptorControlsContext();
        iIgnoreAsyncOpComplete = !adaptorControlsContext;
            // if we don't control context, always send a PreemptionFinishedCallbackReceived()
		iStateEventReceived=EFalse;
        }

    else if (aEvent == KUidA3FContextPreEmption)
        {
        // clear iBeingPreepted - will be set in ContextEventPreEmption if req
        iBeingPreempted=EFalse;
        iPreemptionClash=EFalse; // clear pre-emption clash flag
        TBool adaptorControlsContext = iAdaptationObserver->AdaptorControlsContext();
		iStateEventReceived=EFalse;
        iIgnoreAsyncOpComplete=EFalse; // clear being iIgnoreAsyncOpComplete
        ContextEventPreEmption(aEvent, aError);
        if (!adaptorControlsContext)
            {
            iIgnoreAsyncOpComplete = ETrue; // if we don't control context never do AsyncOpComplete
            }
        }
    else if (aEvent == KUidA3FContextPreEmptedCommit)
        {
		DP0(DLINFO,"KUidA3FContextPreEmptedCommit event received, thus clash with Pre-emption");
        // clear iBeingPreepted - will be set in ContextEventPreEmption if req
        iBeingPreempted=EFalse;
        TBool adaptorControlsContext = iAdaptationObserver->AdaptorControlsContext();
        if (adaptorControlsContext)
        	{
			// push current request that was being processed onto front of queue.
        	iAdaptationObserver->PreemptionClash();
        	iPreemptionClash=ETrue;
        	}
		iStateEventReceived=EFalse;
        iIgnoreAsyncOpComplete=EFalse; // clear being iIgnoreAsyncOpComplete
        ContextEventPreEmption(aEvent, aError);
        if (!adaptorControlsContext)
            {
            iIgnoreAsyncOpComplete = ETrue; // if we don't control context never do AsyncOpComplete
            }
        }

    else if (aEvent == KUidA3FContextAbort)
        {
        ContextEventAbort(aError);
        }

    DP_OUT();
    }


void CDevCommonControl::ContextEventAsynchronousPlayCompletion(TInt aError) // from CDevCommonControl
    {
    DP_CONTEXT(CDevCommonControl::ContextEventAsynchronousPlayCompletion, CtxDevSound, DPLOCAL);
    DP_IN();
    
	iAdaptationObserver->AsynchronousOperationComplete(aError, ETrue);
		
    if (aError)
        {
        FinishWithError(aError);
        }
           
    DP_OUT();
    }


void CDevCommonControl::ContextEventAsynchronousInitializeComplete(TInt aError) // from CDevCommonControl
    {
    DP_CONTEXT(CDevCommonControl::ContextEventAsynchronousInitializeComplete, CtxDevSound, DPLOCAL);
    DP_IN();
    
    iAdaptationObserver->AsynchronousOperationComplete(aError, ETrue);
    iAdaptationObserver->InitializeComplete(aError);
    
    DP_OUT();
    }


void CDevCommonControl::ContextEventUpdateComplete(TInt aError) // from CDevCommonControl
    {
    DP_CONTEXT(CDevCommonControl::ContextEventUpdateComplete, CtxDevSound, DPLOCAL);
    DP_IN();
    
    if (iStateEventReceived)
        {
        iStateEventReceived = EFalse;
        DP0(DLINFO,"Context event for that does involve state change");         
        
        if (aError)
            {
            ContextEventUpdateWithStateEventAndError(aError);
            }
        else
            {
            ContextEventUpdateWithStateEventNoError();
            }   
        DP_OUT();
        return;
        }
    
    DP0(DLINFO,"Context event for that doesn't involve state change");

    if (aError)
        {
        ContextEventUpdateWithoutStateEventButWithError(aError);
        }
    else
        {
        ContextEventUpdateWithoutStateEventNoError();
        }
    
    DP_OUT();
    }


void CDevCommonControl::ContextEventPreEmption(TUid aEvent, TInt aError) // from CDevCommonControl
    {
    DP_CONTEXT(CDevCommonControl::ContextEventPreEmption, CtxDevSound, DPLOCAL);
    DP_IN();
    
    DP1(DLERR,"Preemption error=%d", aError);
    CDevAudioControl::ContextEvent(aEvent, aError);
    iBeingPreempted=ETrue;
        
    DP_OUT();
    }


void CDevCommonControl::ContextEventAbort(TInt aError) // from CDevCommonControl
    {
    DP_CONTEXT(CDevCommonControl::ContextEventAbort, CtxDevSound, DPLOCAL);
    DP_IN();
    
    DP1(DLERR,"Abort error=%d", aError);
    FinishWithError(aError==KErrAbort ? KErrDied:aError);
    
    DP_OUT();
    }


void CDevCommonControl::ContextEventStopDevSoundNotifications() // from CDevCommonControl
    {
    DP_CONTEXT(CDevCommonControl::ContextEventStopDevSoundNotifications, CtxDevSound, DPLOCAL);
    DP_IN();
    
    iDevAudio->iAudioStream->UnregisterAudioStreamObserver(*this);
    iGainControl->UnregisterAudioGainControlObserver(*this);
    iAudioCodecIf->UnregisterAudioCodecObserver(*this);
    iAudioCodecIf = NULL;
    
    DP_OUT();
    }


void CDevCommonControl::ContextEventPauseResumeSequenceDueToEmptyBuffers(TBool aFlush) // from CDevCommonControl
    {
    DP_CONTEXT(CDevCommonControl::ContextEventPauseResumeSequenceDueToEmptyBuffers, CtxDevSound, DPLOCAL);
    DP_IN();
    
    TInt err(KErrNone);

    if (iPauseResumeSequenceDueToEmptyBuffers)
        {
        if (aFlush)
            {
            err = iDevAudio->iAudioStream->Flush();
            }
        
        if ((err) or (aFlush==EFalse))
            {
            iPauseResumeSequenceDueToEmptyBuffers = EFalse;
            iAdaptationObserver->CallbackFromAdaptorReceived(KCallbackFlushComplete, err);
            }
        }
    else
        {
        iAdaptationObserver->AsynchronousOperationComplete(KErrNone, ETrue);    
        }
    
    DP_OUT();
    }


void CDevCommonControl::ContextEventStateDevSoundAdaptorUnloading() // from CDevCommonControl
    {
    DP_CONTEXT(CDevCommonControl::ContextEventStateDevSoundAdaptorUnloading, CtxDevSound, DPLOCAL);
    DP_IN();
    
    // Due destruction sequence or reinitialization
    if (iDevAudio->iClosing or iDevAudio->iReinitializing)
        {
        TInt err = Uninitialize();
        if (err and iDevAudio->iReinitializing)
            {
            ContextEventAsynchronousInitializeComplete(err);
    
            }
        
        DP_OUT();
        return;
        }

    // Notify the user that ProcessingFinished is complete. 
    // Stop call complete, sent callback.
    if (iCallbackFromAdaptor != KCallbackNone)
        {
        iAdaptationObserver->AsynchronousOperationComplete(KErrNone, ETrue);
        
        if (iCallbackFromAdaptor == KCallbackProcessingFinished)
            {
            FinishWithError(KErrUnderflow);
            }
        else if (iCallbackFromAdaptor == KCallbackProcessingUnitError)
            {
            FinishWithError(iProcessingUnitError);
            }
        
        iCallbackFromAdaptor = KCallbackNone;
        DP_OUT();
        return;
        }
    
    // Error condition
    if (iErrorCondition)
        {
        FinishWithError(iErrorCondition);
        iErrorCondition = KErrNone;
        }
    else
        {
    
        iAdaptationObserver->AsynchronousOperationComplete(KErrNone, ETrue);
        }
    
    DP_OUT();
    }


void CDevCommonControl::ContextEventStateDevSoundAdaptorLoading() // from CDevCommonControl
    {
    DP_CONTEXT(CDevCommonControl::ContextEventStateDevSoundAdaptorLoading, CtxDevSound, DPLOCAL);
    DP_IN();
    
    iDevAudio->RequestGainAndBalance(this); // TODO handle error

    TInt err = iDevAudio->iAudioStream->Activate();
    if (err)
        {
        DP_OUT();
        return;
        }
    
    err = iDevAudio->CommitAudioContext();
    if (err)
        {
        ContextEventAsynchronousPlayCompletion(err);
        DP_OUT();
        return;
        }
    
    iDevAudio->iActiveState = EDevSoundAdaptorActivating;
    iAdaptationObserver->AsynchronousOperationComplete(KErrNone, EFalse);
    
    DP_OUT();
    }


void CDevCommonControl::ContextEventStateDevSoundAdaptorStopping() // from CDevCommonControl
    {   
    DP_CONTEXT(CDevCommonControl::ContextEventStateDevSoundAdaptorStopping, CtxDevSound, DPLOCAL);
    DP_IN();
    
    TInt err = Unload();
    if (err)
        {
        DP0(DLINFO,"Commit failed during stopping");
        FinishWithError(err);
        }
    
    __ASSERT_DEBUG(err==KErrNone, Panic(ECommitFailedDuringStop));
    
    DP_OUT();
    }


void CDevCommonControl::ContextEventStateDevSoundAdaptorBeingPreempted() // from CDevCommonControl
    {
    DP_CONTEXT(CDevCommonControl::ContextEventStateDevSoundAdaptorBeingPreempted, CtxDevSound, DPLOCAL);
    DP_IN();
    
    __ASSERT_DEBUG(iDevAudio->iActiveStreamState == EInitialized, Panic(EStreamBeingDemotedToEIdle));
    FinishWithError(KErrInUse);
    if (iIgnoreAsyncOpComplete)
        {
        iAdaptationObserver->PreemptionFinishedCallbackReceived(ETrue);
        iIgnoreAsyncOpComplete=EFalse;
        DP_OUT();
        return;
        }
    
    ContextEventPauseResumeSequenceDueToEmptyBuffers(EFalse);
    
    DP_OUT();
    }


void CDevCommonControl::ContextEventStateDevSoundAdaptorUninitializing() // from CDevCommonControl
    {
    DP_CONTEXT(CDevCommonControl::ContextEventStateDevSoundAdaptorUninitializing, CtxDevSound, DPLOCAL);
    DP_IN();
    TInt err = RemoveProcessingUnits();

    if (err == KErrNone)
        {
        iDevAudio->iActiveState = EDevSoundAdaptorRemovingProcessingUnits;
        }
    else if (iDevAudio->iReinitializing)
        {
        ContextEventAsynchronousInitializeComplete(err);
        }
    
    DP_OUT();
    }


void CDevCommonControl::ContextEventErrorStateDevSoundAdaptorActivating(TInt aError) // from CDevCommonControl
    {
    DP_CONTEXT(CDevCommonControl::ContextEventErrorStateDevSoundAdaptorActivating, CtxDevSound, DPLOCAL);
    DP_IN();

    // If the resume operation fails as result of EmptyBuffers
    // Notify about operation complete through CallbackFromAdaptorReceived
    // and continue to allow client to receive PlayError()
    if (iPauseResumeSequenceDueToEmptyBuffers)
        {
        iPauseResumeSequenceDueToEmptyBuffers = EFalse;
        iAdaptationObserver->CallbackFromAdaptorReceived(KCallbackFlushComplete, KErrNone);
        }
    
    iErrorCondition = aError;
    
    TInt err = Unload();
    if (err)
        {
        DP0(DLINFO,"Commit failed during stopping");
        FinishWithError(err);
        }
    __ASSERT_DEBUG(err==KErrNone, Panic(ECommitFailedDuringStop));
    
    DP_OUT();
    }


void CDevCommonControl::ContextEventErrorStateDevSoundAdaptorBeingPreempted() // from CDevCommonControl
    {
    DP_CONTEXT(CDevCommonControl::ContextEventErrorStateDevSoundAdaptorBeingPreempted, CtxDevSound, DPLOCAL);
    DP_IN();
    
__ASSERT_DEBUG(iDevAudio->iActiveStreamState == EInitialized, Panic(EStreamBeingDemotedToEIdle));
    FinishWithError(KErrInUse);

    if(iIgnoreAsyncOpComplete)
        {
        iAdaptationObserver->PreemptionFinishedCallbackReceived(ETrue);
        }
    
    DP_OUT();
    }


void CDevCommonControl::ContextEventUpdateWithoutStateEventNoError() // from CDevCommonControl
    {
    DP_CONTEXT(CDevCommonControl::ContextEventUpdateWithoutStateEventNoError, CtxDevSound, DPLOCAL);
    DP2_IN("iActiveState=%d iIgnoreAsyncOpComplete=%d",iDevAudio->iActiveState, iIgnoreAsyncOpComplete);
    
    if (iDevAudio->iActiveState != EDevSoundAdaptorRemovingProcessingUnits)
        {
	    if (iIgnoreAsyncOpComplete)
	      {
	      iAdaptationObserver->PreemptionFinishedCallbackReceived(ETrue);
	      iIgnoreAsyncOpComplete = EFalse;
	      }
	    else
	      {
	      iAdaptationObserver->AsynchronousOperationComplete(KErrNone, ETrue);
	      }
        DP_OUT();
        return;
        }

    //If the Commit cycle when going into EDevSoundAdaptorRemovingProcessingUnits fails due to pre-emption
    //clash then we re-apply the client request again.
    if (iDevAudio->iActiveState == EDevSoundAdaptorRemovingProcessingUnits && iIgnoreAsyncOpComplete)
    	{
		//Pop front of queue to re-apply the request again via CMMFDevSoundSession::DequeueRequest
		//from the callback into CMMFDevSoundSession below:
		iAdaptationObserver->PreemptionFinishedCallbackReceived(ETrue);
		iIgnoreAsyncOpComplete = EFalse;
		DP_OUT();
		return;
    	}

    iDevAudio->iActiveState = EDevSoundAdaptorCreated_Uninitialised;
    
    if (iDevAudio->iReinitializing)
        {
        ContextEventStopDevSoundNotifications();
        
        TInt err = iDevAudio->Initialize(iDevAudio->iTargetFormat, iDevAudio->iTargetMode);
        if(err)
            {
            ContextEventAsynchronousInitializeComplete(err);
            }

        iDevAudio->iReinitializing = EFalse;
        DP_OUT();
        return;
        }
    
    iDevAudio->iClosing = EFalse;
    iAdaptationObserver->AsynchronousOperationComplete(KErrNone, ETrue);
    
    DP_OUT();
    }


void CDevCommonControl::ContextEventUpdateWithoutStateEventButWithError(TInt aError) // from CDevCommonControl
    {
    DP_CONTEXT(CDevCommonControl::ContextEventUpdateWithoutStateEventButWithError, CtxDevSound, DPLOCAL);
    DP_IN();

    //If flag is true below then it must be due to a stateless normal pre-emption or
    //stateless pre-emption clash scenario.
    if(iIgnoreAsyncOpComplete)
    	{
		//If we are in pre-emption clash then callback below will retry the client request again.
		iAdaptationObserver->PreemptionFinishedCallbackReceived(ETrue); // notify client of end of cycle
		iIgnoreAsyncOpComplete = EFalse;
    	}
    else
    	{
        TDevSoundAdaptorState previousState = iDevAudio->iPreviousState;

        DP3(DLINFO,"Error with no state change, state %d, previous %d, error %d during Commit cycle",
                    iDevAudio->iActiveState, previousState, aError);

        // We can end up here for a number of reasons. For non "mid states", this is
        // a standard error scenario. For some mid-states (e.g. Activating, Loading etc),
        // when we try and "promote" the state, this happens when the promotion is rejected
        // and we handle thus accordingly. For other mid-states the situation is less clear
        // and we call AsynchronousOperationComplete() with the error assuming the parent
        // session will deal with it. Whatever we don't want to stay in a mid-state, so
        // rewind to the previous ("normal") one if we are in one.

        // Longer term TODO. If the code were refactored so that the InitializeComplete(),
        // PlayError() etc callback came from AsynchronousOperationComplete() then the
        // following code might be simpler. Most of the time (at least) we get here because
        // we are doing a session function, and we can use the function to determine what
        // to do more easily than relying on the state. As it is, for some mid-states we
        // try and work out what error code to generate. Not clear this covers 100% cases,
        // although demotion transitions should not fail, so the problem cases might not occur.
        //

		//If we reach this condition then it is because of rejection/error during Commit cycle.
		switch (iDevAudio->iActiveState)
			{
			case EDevSoundAdaptorInitialising:
				{
				iDevAudio->iActiveState = previousState;
				ContextEventAsynchronousInitializeComplete(aError);
				break;
				}
			case EDevSoundAdaptorLoading:
				{
				iDevAudio->iActiveState = previousState;
				ContextEventAsynchronousPlayCompletion(aError);
				break;
				}
			case EDevSoundAdaptorActivating:
				{
				iDevAudio->iActiveState = previousState;
				ContextEventAsynchronousPlayCompletion(aError);
				break;
				}
			case EDevSoundAdaptorRemovingProcessingUnits:
			case EDevSoundAdaptorUninitialising:
			case EDevSoundAdaptorUnloading:
			case EDevSoundAdaptorStopping:
			case EDevSoundAdaptorPausing:
			    {
                DP2(DLINFO,"Unexpected mid state [%d] when handling error [%d] during Commit cycle, workback", iDevAudio->iActiveState, aError);
			    iDevAudio->iActiveState = previousState;
                iAdaptationObserver->AsynchronousOperationComplete(aError, ETrue);
			    break;
			    }
			default:
				{
				DP2(DLINFO,"Unexpected state [%d] when handling error [%d] during Commit cycle", iDevAudio->iActiveState, aError);
		        iAdaptationObserver->AsynchronousOperationComplete(aError, ETrue);
				}
			}
    	}
       
    DP_OUT();
    }


void CDevCommonControl::ContextEventUpdateWithStateEventNoError() // from CDevCommonControl 
    {
    DP_CONTEXT(CDevCommonControl::ContextEventUpdateWithStateEventNoError, CtxDevSound, DPLOCAL);
    DP_IN();

    switch (iDevAudio->iActiveState)
        {
    case EDevSoundAdaptorUninitialising:
        iDevAudio->iActiveState = EDevSoundAdaptorUnitialised_Uninitialised;
        ContextEventStateDevSoundAdaptorUninitializing();
        break;

    case EDevSoundAdaptorInitialising:
        iDevAudio->iActiveState = EDevSoundAdaptorInitialised_Initialised;
        ContextEventAsynchronousInitializeComplete(KErrNone);
        break;

    case EDevSoundAdaptorUnloading:
        iDevAudio->iActiveState = EDevSoundAdaptorInitialised_Initialised;
        ContextEventStateDevSoundAdaptorUnloading();
        break;

    case EDevSoundAdaptorLoading:
        iDevAudio->iActiveState = EDevSoundAdaptorGoingActive;
        ContextEventStateDevSoundAdaptorLoading();
        break;

    case EDevSoundAdaptorStopping:
        iDevAudio->iActiveState = EDevSoundAdaptorInitialised_Idle;
        ContextEventStateDevSoundAdaptorStopping();
        break;

    case EDevSoundAdaptorActivating:
        iDevAudio->iActiveState = EDevSoundAdaptorActive_Active;
        ContextEventPauseResumeSequenceDueToEmptyBuffers(EFalse);
        break;
        
    case EDevSoundAdaptorPausing:
        iDevAudio->iActiveState = EDevSoundAdaptorPaused_Primed;
        ContextEventPauseResumeSequenceDueToEmptyBuffers(ETrue);
        break;

    case EDevSoundAdaptorBeingPreempted:
        iDevAudio->iActiveState = EDevSoundAdaptorInitialised_Initialised;
        ContextEventStateDevSoundAdaptorBeingPreempted();
        break;
        
    default:
        break;
        }   
    
    DP_OUT();
    }


void CDevCommonControl::ContextEventUpdateWithStateEventAndError(TInt aError) // from CDevCommonControl
    {
    DP_CONTEXT(CDevCommonControl::ContextEventUpdateWithStateEventAndError, CtxDevSound, DPLOCAL);
    DP_IN();

    DP1(DLERR,"ContextEventUpdateWithStateEventAndError error=%d", aError);
    
    switch(iDevAudio->iActiveState)
        {
    case EDevSoundAdaptorInitialising:
        iDevAudio->iActiveState = EDevSoundAdaptorCreated_Uninitialised;
        iAdaptationObserver->InitializeComplete(aError);
        break;
        
    case EDevSoundAdaptorLoading:
        iDevAudio->iActiveState = EDevSoundAdaptorInitialised_Initialised;
        FinishWithError(aError);
        break;
        
    case EDevSoundAdaptorActivating:
        iDevAudio->iActiveState = EDevSoundAdaptorInitialised_Idle;
        ContextEventErrorStateDevSoundAdaptorActivating(aError);
        break;
        
    case EDevSoundAdaptorBeingPreempted:
        iDevAudio->iActiveState = EDevSoundAdaptorInitialised_Initialised;
        ContextEventErrorStateDevSoundAdaptorBeingPreempted();
        break;

    default:
        break;
        }
    
    iCallbackFromAdaptor = KCallbackNone;
    
    if(!iIgnoreAsyncOpComplete)
        {
        iAdaptationObserver->AsynchronousOperationComplete(aError, ETrue);
        }
    else
        {
        iAdaptationObserver->PreemptionFinishedCallbackReceived(ETrue);
        iIgnoreAsyncOpComplete=EFalse;
        }
    
    DP_OUT();
    }


// end of file
