sl@0: // Copyright (c) 2005-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: #ifndef __GAVDPSTATEMACHINE_H__
sl@0: #define __GAVDPSTATEMACHINE_H__
sl@0: 
sl@0: #include <e32base.h>
sl@0: #include <bttypes.h> //TBTDevAddr
sl@0: #include <es_sock.h> //RSocketServer, RSocket
sl@0: #include <gavdp.h> //MGavdpUser, RGavdp
sl@0: #include <bluetoothav.h> //TAvdtpSEPInfo, TSEID
sl@0: #include <mmf/common/mmfutilities.h> //TFourCC
sl@0: #include <mmf/server/sounddevice.h> //TMMFStereoSupport
sl@0: #include "GavdpStates.h"
sl@0: 
sl@0: 
sl@0: const TUint KGAVDPCallbackTimeout = 30000000;
sl@0: 
sl@0: class CGavdpTimeout; //fwd ref
sl@0: class CA2dpAudioCodecConfiguration;
sl@0: 
sl@0: using namespace SymbianSBC;
sl@0: using namespace SymbianBluetoothAV;	
sl@0: 
sl@0: /**
sl@0: structure used internally in the GAVDP state machine to keep
sl@0: track of seps than can be used on the headset to send audio and 
sl@0: the local symbian device SEPs
sl@0: */
sl@0: struct TUsableSEP
sl@0: 	{
sl@0: 	TSEID iSEID;
sl@0: 	TFourCC iDataType;
sl@0: 	};
sl@0: 	
sl@0: /**
sl@0: Callback class implemented by CA2dpBTHeadsetAudioInterface to get events
sl@0: back from CGAVDPStateMachine
sl@0: */	
sl@0: class MGAVDPStateChangeObserver
sl@0: 	{
sl@0: public:
sl@0: /**
sl@0: Callback when the CGAVDPStateMachine has completed a state change
sl@0: initiated by a call to ChangeState
sl@0: 
sl@0: @internalComponent
sl@0: @param aInitialState The state the CGAVDPStateMachine prior to calling ChangeState
sl@0: @param standard SymbianOS error
sl@0: */
sl@0: 	void virtual GAVDPStateChangeComplete(const TGAVDPState& aInitialState, TInt aError) = 0;
sl@0: 	
sl@0: /**
sl@0: Callback when the GAVDPStateMachine detects an error condition
sl@0: event while no state change is in progress
sl@0: 
sl@0: @internalComponent
sl@0: @param aError standard SymbianOS error
sl@0: */
sl@0: 	void virtual GAVDPStateMachineEvent(TInt aError) = 0;
sl@0: 	
sl@0: /**
sl@0: Callback when the headset suspends the streaming
sl@0: 
sl@0: @internalComponent
sl@0: */
sl@0: 	void virtual GAVDPStateMachineStreamSuspendedByRemoteHeadset() = 0;
sl@0: 	
sl@0: /**
sl@0: Callback when the headset requested a reconfiguration of the settings
sl@0: 
sl@0: @internalComponent
sl@0: @return an error code indicating whether it was possible to perform the reconfiguration
sl@0: */
sl@0: 	TInt virtual GAVDPStateMachineReconfigureByRemoteHeadset() = 0;
sl@0: 	
sl@0: /**
sl@0: Callback when the headset starts (or restarts) the streaming
sl@0: 
sl@0: @internalComponent
sl@0: */
sl@0: 	void virtual GAVDPStateMachineStreamResumedByRemoteHeadset() = 0;
sl@0: 	};
sl@0: 
sl@0: 
sl@0: /**
sl@0: GAVDP state machine used by the CA2dpBTHeadsetAudioInterface.
sl@0: This class is used by the CA2dpBTHeadsetAudioInterface to
sl@0: initialize and open the headset, which involved finding SEPs,
sl@0: configuring , getting a bearer and streaming.  The CGAVDPStateMachine
sl@0: uses the MGAVDPStateChangeObserver callback to inform the CA2dpBTHeadsetAudioInterface
sl@0: of when the state change is complete, error conditions, and state changes
sl@0: initiated by the headset itself
sl@0:  
sl@0: @internalComponent
sl@0: */
sl@0: NONSHARABLE_CLASS(CGAVDPStateMachine) : public CActive, public MGavdpUser  
sl@0: 	{
sl@0: 	friend class CGavdpTimeout;
sl@0: public:
sl@0: 	static CGAVDPStateMachine* NewL(MGAVDPStateChangeObserver& aGAVDPStateChangeObserver, CA2dpAudioCodecConfiguration& aA2dpCodecSettings, RSocketServ& aSocketServer);
sl@0: 	~CGAVDPStateMachine();
sl@0: 	void SetBTAddress(const TBTDevAddr& aRemoteAddress);
sl@0: 	TInt Reconfigure(TBool aSettingsHaveChanged);
sl@0: 	TInt ChangeState(const TGAVDPState& aNewState);
sl@0: 	void CancelChangeState(); //external request to cancel state change
sl@0: 	TGAVDPState State() const;
sl@0: 	RArray<TUsableSEP>& UsableSEPs() const;
sl@0: 	RSocket& BearerSocket() const;
sl@0: 	TBTDevAddr& BTAddress() const;
sl@0: 	TInt CodecCaps(TAvdtpMediaCodecCapabilities*& aCodecCaps) const;
sl@0: 	
sl@0: 	//used by a2dp instead of CodecCaps
sl@0: 	TAvdtpMediaCodecCapabilities* RemoteCodecConfiguration();
sl@0: private:
sl@0: 	CGAVDPStateMachine(MGAVDPStateChangeObserver& aGAVDPStateChangeObserver, CA2dpAudioCodecConfiguration& aA2dpCodecSettings, RSocketServ& aSocketServer); 
sl@0: 	void ConstructL();
sl@0: 	TInt RegisterLocalSEP();
sl@0: 	void ConnectToGAVDP();
sl@0: 	void DiscoverRemoteSEPs();
sl@0: 	void GetRemoteSEPCapability();
sl@0: 	void GetRemoteSEPCapabilities();
sl@0: 	void ConfigureSEP();
sl@0: 	TInt ConfigureLocalSEP();
sl@0: 	TInt ConfigureRemoteSEP();
sl@0: 	void CreateBearerSocket();
sl@0: 	void StartStream();
sl@0: 	void SuspendStream();
sl@0: 	
sl@0: 	void NextState();
sl@0: 	void StateChangeComplete();
sl@0: 	void CancelChangeState(TInt aReason); //internal request to cancel state change eg due to an error condition
sl@0: 	void Reset(); //utility to reset state to idle and all variables
sl@0:  	
sl@0: 	//MGavdpUser
sl@0: 	virtual void GAVDP_ConnectConfirm(const TBTDevAddr& aDevice);
sl@0: 	virtual void GAVDP_SEPDiscovered(const TAvdtpSEPInfo& aSEP);
sl@0: 	virtual void GAVDP_SEPDiscoveryComplete();	
sl@0: 	virtual void GAVDP_SEPCapability(TAvdtpServiceCapability* aCapability);
sl@0: 	virtual void GAVDP_SEPCapabilityComplete();		
sl@0: 	virtual void GAVDP_AbortStreamConfirm();
sl@0: 	virtual void GAVDP_StartStreamsConfirm();	
sl@0: 	virtual void GAVDP_SuspendStreamsConfirm();
sl@0: 	virtual void GAVDP_SecurityControlConfirm(const TDesC8& /*aResponseData*/) {};	
sl@0: 	virtual void GAVDP_ConfigurationConfirm();
sl@0: 	virtual void GAVDP_ConfigurationStartIndication(TSEID aLocalSEID, TSEID aRemoteSEID);
sl@0: 	virtual TInt	GAVDP_ConfigurationIndication(TAvdtpServiceCapability* aCapability);
sl@0: 	virtual TInt	GAVDP_ConfigurationEndIndication();
sl@0: 	virtual TInt	GAVDP_StartIndication(TSEID aSEID);
sl@0: 	virtual TInt	GAVDP_SuspendIndication(TSEID aSEID);
sl@0: 	virtual TInt	GAVDP_SecurityControlIndication(TSEID /*aSEID*/, TDes8& /*aSecurityData*/) {return KErrNotSupported;};
sl@0: 	virtual void GAVDP_AbortIndication(TSEID aSEID);
sl@0: 	virtual void GAVDP_ReleaseIndication(TSEID aSEID);
sl@0: 	virtual void GAVDP_BearerReady(RSocket aSocket, const TAvdtpSockAddr& aAddress);
sl@0: 	virtual void GAVDP_Error(TInt aError, const TDesC8& aErrorData);
sl@0: 
sl@0: 	//CActive
sl@0: 	void RunL();
sl@0: 	void DoCancel();
sl@0: private:
sl@0: 	MGAVDPStateChangeObserver& iGAVDPStateChangeObserver;
sl@0: 	TGAVDPState iInitialState;
sl@0: 	TGAVDPState iCurrentState;
sl@0: 	TGAVDPState iNextState;
sl@0: 	TGAVDPState	iTargetState;
sl@0: 	TConfigurationByRemoteHeadsetState iConfigurationByRemoteHeadsetState;
sl@0: 	CA2dpAudioCodecConfiguration& iA2dpCodecSettings;
sl@0: 	TBool iLocalSEPConfigured;
sl@0: 	TBool iChangeOfSelectedHeadsetSEP;
sl@0: 	TBTDevAddr iBTDevAddr;
sl@0: 	TBool iStateChangeInProgress;
sl@0: 	RSocketServ& iSocketServer;
sl@0: 	RSocket iBearerSocket;
sl@0: 	RGavdp		iGavdp;
sl@0: 	TSEID		iSymbianDeviceSEID;
sl@0: 	TSEID		iHeadsetSEID;
sl@0: 	RArray<TSEID> iPotentialSEPs;
sl@0: 	RArray<TUsableSEP> iSymbianDeviceSEPs;
sl@0: 	RArray<TUsableSEP> iUsableSEPs; //SEPs that can actually be used to stream audio
sl@0: 	RPointerArray<TAvdtpServiceCapability> iSEPCapabilities;
sl@0: 	TUint iSEPIterator; //used to iterate through potential SEPs when getting caps
sl@0: 	TUint iSEPCapabilityEntry;
sl@0: 	
sl@0: 	//heap members owned by CGAVDPStateMachine
sl@0: 	CGavdpTimeout* iSignallingTransactionTimeout;
sl@0: 	};
sl@0: 	
sl@0: /**
sl@0: The SEP discovery and GetCapabilities do not have built in timeouts,
sl@0: so a timeout is required
sl@0: 
sl@0: @internalComponent
sl@0: */
sl@0: NONSHARABLE_CLASS(CGavdpTimeout) : public CTimer
sl@0: 	{
sl@0: public:
sl@0: 	static CGavdpTimeout* NewL(CGAVDPStateMachine& aGAVDPStateMachine);
sl@0: 	void StartTimer(TTimeIntervalMicroSeconds32 aTimeInterval);
sl@0: private:
sl@0: 	CGavdpTimeout();
sl@0: 	void ConstructL(CGAVDPStateMachine& aGAVDPStateMachine);
sl@0: 	virtual void RunL();
sl@0: private:
sl@0: 	CGAVDPStateMachine* iGAVDPStateMachine;
sl@0: 	};
sl@0: 	
sl@0: 
sl@0: #endif
sl@0: