bluetoothengine/btsac/src/btsacStateStreaming.cpp
changeset 0 f63038272f30
child 1 6a1fe72036e3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bluetoothengine/btsac/src/btsacStateStreaming.cpp	Mon Jan 18 20:28:57 2010 +0200
@@ -0,0 +1,364 @@
+/*
+* Copyright (c) 2002-2005 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:  In this state, streaming is active.
+*
+*/
+
+
+
+
+// INCLUDE FILES
+#include "btsacStateStreaming.h"
+#include "btsacStateListening.h"
+#include "btsacStateSuspended.h"
+#include "btsacStateConnected.h"
+#include "btsacStateAborting.h"
+#include "btsacactive.h"
+#include "btsacGavdp.h"
+#include "btsacSEPManager.h"
+#include "btsacStreamerController.h"
+#include "debug.h"
+
+// A2DP codec-specific element definitions
+// in bluetoothAV.h
+using namespace SymbianBluetoothAV;   
+
+// Subband codec-specific values
+// in bluetoothAV.h
+using namespace SymbianSBC;   
+
+
+// ================= MEMBER FUNCTIONS =======================
+
+// -----------------------------------------------------------------------------
+// CBtsacStreaming::NewL
+// -----------------------------------------------------------------------------
+//
+CBtsacStreaming* CBtsacStreaming::NewL(CBTSAController& aParent, TAudioOpenedBy aAudioOpenedBy, TBool aStartCollision)
+    {
+    CBtsacStreaming* self = new( ELeave ) CBtsacStreaming(aParent, aAudioOpenedBy, aStartCollision);
+    return self;
+    }
+
+// -----------------------------------------------------------------------------
+// CBtsacStreaming::CBtsacStreaming
+// -----------------------------------------------------------------------------
+//
+CBtsacStreaming::CBtsacStreaming(CBTSAController& aParent, TAudioOpenedBy aAudioOpenedBy, TBool aStartCollision)
+:   CBtsacState(aParent, EStateStreaming), iSuspending(EFalse), iAudioOpenedBy(aAudioOpenedBy),
+	iStartCollision(aStartCollision)
+    {
+    }
+  
+// -----------------------------------------------------------------------------
+// CBtsacStreaming::~CBtsacStreaming
+// -----------------------------------------------------------------------------
+//    
+CBtsacStreaming::~CBtsacStreaming()
+    {
+    TRACE_FUNC
+    }
+
+// -----------------------------------------------------------------------------
+// CBtsacStreaming::EnterL
+// -----------------------------------------------------------------------------
+//
+void CBtsacStreaming::EnterL()
+    {
+	TRACE_STATE(_L("[BTSAC State] Streaming"))
+	_LIT(KName, "CBtsacStateStreaming");
+	const TDesC& Name = KName;
+	Parent().iGavdp->RegisterObserver(this, Name);
+	if( iAudioOpenedBy == EAudioOpenedByAcc )
+	 	{
+ 		Parent().AccessoryOpenedAudio(Parent().GetRemoteAddr());
+	 	}
+    }
+
+// -----------------------------------------------------------------------------
+// CBtsacStreaming::CancelActionL
+// -----------------------------------------------------------------------------
+//
+void CBtsacStreaming::CancelActionL(TInt aError, TBTSACGavdpResetReason aGavdpReset)
+	{
+	TRACE_FUNC
+	TInt ret = Parent().iStreamer->StopStream();
+	if ( ret )
+		{
+		TRACE_INFO((_L("CBtsacStreaming::Cancel() iStreamer.StopStream() returned error(%d) !!!"), ret))
+		}
+	Parent().CompletePendingRequests(KCompleteAllReqs, aError);
+	Parent().ChangeStateL(CBtsacListening::NewL(Parent(), aGavdpReset, aError));
+	}
+
+// -----------------------------------------------------------------------------
+// CBtsacStreaming::OpenAudioLinkL
+// -----------------------------------------------------------------------------
+//
+void CBtsacStreaming::OpenAudioLinkL(const TBTDevAddr& /*aAddr*/)
+	{  
+	TRACE_FUNC
+	// It is not allowed to open audio in streaming state, audio is allready opened
+	// by an accessory. Inform accessory fw about this by returning KErrInUse.
+	Parent().CompletePendingRequests(KOpenAudioReq, KErrInUse);
+	}
+
+// -----------------------------------------------------------------------------
+// CBtsacStreaming::CloseAudioLinkL
+// -----------------------------------------------------------------------------
+//
+void CBtsacStreaming::CloseAudioLinkL(const TBTDevAddr& /*aAddr*/)
+	{  
+	TRACE_FUNC
+	iStartCollision = EFalse;
+	TInt ret = Parent().iStreamer->StopStream();
+	if ( ret )
+		{
+		TRACE_INFO((_L("CBtsacStreaming::CloseAudio() iStreamer.StopStream() returned error(%d) !!!"), ret))
+		}
+	TAvdtpSEPInfo SEPInfo;
+	ret = Parent().iRemoteSEPs->GetInfo(Parent().GetSEPIndex(), SEPInfo); 
+	if ( ret )
+		{
+		TRACE_INFO((_L("CBtsacStreaming::CloseAudio() Couldn't retrieve SEP Info !")))
+		CancelActionL(KErrCancel, EGavdpResetReasonGeneral); 
+ 		return;   
+		}
+	// Suspend audio
+	TSEID remoteSEPid = SEPInfo.SEID(); 	
+	TRACE_INFO((_L("CBtsacStreaming::CloseAudio() Suspending remote SEID(%d)"), remoteSEPid.SEID()))	
+	iSuspending = ETrue;
+	Parent().iGavdp->SuspendStreams(remoteSEPid);
+	}
+
+// -----------------------------------------------------------------------------
+// CBtsacStreaming::CancelCloseAudioLink
+// -----------------------------------------------------------------------------
+//
+void CBtsacStreaming::CancelCloseAudioLink(const TBTDevAddr& /*aAddr*/)
+	{
+	TRACE_FUNC
+	// For safety sake complete all pending requests
+	Parent().CompletePendingRequests(KCompleteAllReqs, KErrNone);
+	TRAP_IGNORE(Parent().ChangeStateL(CBtsacListening::NewL(Parent(), EGavdpResetReasonGeneral, KErrDisconnected)));
+	}
+
+
+// -----------------------------------------------------------------------------
+// CBtsacStreaming::StartRecording
+// -----------------------------------------------------------------------------
+//
+void CBtsacStreaming::StartRecording()
+	{  
+	TRACE_FUNC	
+	iStartCollision = EFalse;
+	if ( Parent().iStreamer->StartStream(Parent().iStreamingSockets[0], Parent().iStreamer->FrameLength()) != KErrNone ) 
+	 	{
+		TRACE_INFO((_L("CBtsacStreaming::StartRecording() [ERR] Could not start streaming!")))	
+		TInt err = Parent().AbortStream();
+		if(err)
+			{
+			TRACE_INFO((_L("CBtsacStreaming::StartRecording() Couldn't abort stream.")))	
+			}
+		TRAP_IGNORE(Parent().ChangeStateL(CBtsacListening::NewL(Parent(), EGavdpResetReasonNone, KErrDisconnected)));
+	 	}
+	}
+
+// -----------------------------------------------------------------------------
+// CBtsacStreaming::DisconnectL
+// -----------------------------------------------------------------------------
+//
+void CBtsacStreaming::DisconnectL()
+	{
+	TRACE_FUNC
+	TInt ret = Parent().iStreamer->StopStream();
+	if ( ret )
+		{
+		TRACE_INFO((_L("CBtsacStreaming::DisconnectL() StopStream() returned error: %d"), ret))	
+		}
+	Parent().CompletePendingRequests(KDisconnectReq, ret);
+	Parent().ChangeStateL(CBtsacListening::NewL(Parent(), EGavdpResetReasonDisconnect, KErrNone));
+	}
+
+// -----------------------------------------------------------------------------
+// CBtsacStreaming::GAVDP_SuspendStreamsConfirm
+// -----------------------------------------------------------------------------
+//
+void CBtsacStreaming::GAVDP_SuspendStreamsConfirm()
+	{
+	TRACE_FUNC
+    // so remote supports suspend 
+    iSuspending = EFalse;
+	Parent().CompletePendingRequests(KCloseAudioReq, KErrNone);
+	TRAP_IGNORE(Parent().ChangeStateL(CBtsacSuspended::NewL(Parent())));
+	}
+
+// -----------------------------------------------------------------------------
+// CBtsacStreaming::GAVDP_AbortIndication
+// -----------------------------------------------------------------------------
+//	
+void CBtsacStreaming::GAVDP_AbortIndication(TSEID aSEID)
+	{
+	TRACE_INFO((_L("CBtsacStreaming::GAVDP_AbortIndication() Local SEP Id: %d"), aSEID.SEID()))	
+	(void)aSEID;
+	TInt ret = Parent().iStreamer->StopStream();
+	if ( ret )
+		{
+		TRACE_INFO((_L("CBtsacStreaming::Cancel() iStreamer.StopStream() returned error(%d) !!!"), ret))
+		}
+	
+	// It is possible the remote disconnected while we have active close audio request.
+	Parent().CompletePendingRequests(KCompleteAllReqs, KErrNone);
+    TRAP_IGNORE(Parent().ChangeStateL(CBtsacListening::NewL(Parent(), EGavdpResetReasonNone, KErrDisconnected)));
+	}
+
+// -----------------------------------------------------------------------------
+// CBtsacStreaming::GAVDP_ReleaseIndication
+// -----------------------------------------------------------------------------
+//
+void CBtsacStreaming::GAVDP_ReleaseIndication(TSEID aSEID)
+	{
+	TRACE_INFO((_L("CBtsacStreaming::GAVDP_ReleaseIndication() aSEID: %d"), aSEID.SEID()))	
+	(void)aSEID;
+	if(!iSuspending)
+		{		
+		TInt ret = Parent().iStreamer->StopStream();
+		if ( ret ) 
+		 	{
+			TRACE_INFO((_L("CBtsacStreaming::GAVDP_ReleaseIndication() [ERR: %d] Could not stop streaming!"), ret))	
+		 	}
+	 	Parent().AccessoryClosedAudio(Parent().GetRemoteAddr());
+		}
+	else
+		{
+		// We are trying to suspend the stream and remote end has sent release indication.
+		// Stream is already stopped but we have pending close audio request, complete it.
+		Parent().CompletePendingRequests(KCloseAudioReq, KErrNone);
+		}
+	Parent().CleanSockets();
+	TRAP_IGNORE(Parent().ChangeStateL(CBtsacConnected::NewL(Parent(), EConnExists)));
+	}
+
+// -----------------------------------------------------------------------------
+// CBtsacStreaming::GAVDP_SuspendIndication
+// -----------------------------------------------------------------------------
+//	
+TInt CBtsacStreaming::GAVDP_SuspendIndication(TSEID aSEID)
+	{
+	TRACE_INFO((_L("CBtsacStreaming::GAVDP_SuspendIndication() aSEID: %d"), aSEID.SEID()))	
+	(void)aSEID;
+	if(!iSuspending)
+		{		
+		TInt ret = Parent().iStreamer->StopStream();
+		if ( ret )
+			{
+			TRACE_INFO((_L("CBtsacStreaming::GAVDP_SuspendIndication() iStreamer.StopStream() returned error(%d) !!!"), ret))	
+			}
+		Parent().AccessorySuspendedAudio(Parent().GetRemoteAddr());
+		TRAPD(err, Parent().ChangeStateL(CBtsacSuspended::NewL(Parent())));
+		if(err)
+			{
+			return KErrNoMemory;
+			}
+		}
+	return KErrNone;
+	}
+
+// -----------------------------------------------------------------------------
+// CBtsacStreaming::HandleGavdpErrorL
+// -----------------------------------------------------------------------------
+//	
+void CBtsacStreaming::HandleGavdpErrorL(TInt aError)
+	{
+	TRACE_FUNC
+	TInt err = KErrNone;
+
+	if(aError == (KErrAvdtpSignallingErrorBase - EAvdtpBadState) && iStartCollision)
+		{
+		// Start stream collision has happened (src and snk have sent start stream cmd simultaneously).
+		// iStreamStartIndCollision flag is set in configured state to indicate possible collision
+		// situations.
+		// Error can be ignored and we can continue streaming.
+		iStartCollision = EFalse;
+		TRACE_INFO((_L("CBtsacStreaming::HandleGavdpErrorL() Ignore error, continue streaming.")))
+		return;
+		}
+
+	if(iSuspending)
+		{
+		iSuspending = EFalse;
+		if(aError == (KErrAvdtpSignallingErrorBase - EAvdtpBadState)) // -18094
+			{
+			// For some reason remote rejected our suspend command. According to the specification
+			// it is acceptor's responsibilty to cope with this situation, so we can move to suspended
+			// state and wait for acceptor's reaction.
+	        Parent().CompletePendingRequests(KCloseAudioReq, KErrNone);
+			Parent().ChangeStateL(CBtsacSuspended::NewL(Parent()));
+		    return;
+			}
+		else if(aError == (KErrAvdtpSignallingErrorBase - EAvdtpNotSupportedCommand)) // -18070 
+			{
+			// remote doesn't support suspend so close audio 
+			Parent().CleanSockets();
+	        Parent().CompletePendingRequests(KCloseAudioReq, KErrNone);
+			Parent().ChangeStateL(CBtsacConnected::NewL(Parent(), EConnExists));
+		    return;
+			}
+		}
+	else
+		{
+		err = Parent().iStreamer->StopStream();
+		if (err)
+	 		{
+			TRACE_INFO((_L("CBtsacStreaming::HandleGavdpErrorL() [error: %d] Could not stop streaming!"), err))
+	 		}
+		}
+	
+	switch (aError)
+		{
+		case KErrAvdtpRequestTimeout: // -18005
+		case (KErrAvdtpSignallingErrorBase - EAvdtpBadState): // 18094
+			{
+			err = Parent().AbortStream();
+			if(!err)
+				{
+				// Complete pending requests in Aborting state
+				Parent().ChangeStateL(CBtsacAborting::NewL(Parent()));
+				}
+			else
+				{
+				Parent().CompletePendingRequests(KCompleteAllReqs, aError);
+				Parent().ChangeStateL(CBtsacListening::NewL(Parent(), EGavdpResetReasonGeneral, KErrDisconnected));
+				}
+			break;
+			}
+		case KErrHCILinkDisconnection: // -6305
+		case KErrDisconnected: // -36
+			{
+			Parent().CompletePendingRequests(KCompleteAllReqs, aError);
+			Parent().ChangeStateL(CBtsacListening::NewL(Parent(), EGavdpResetReasonNone, aError));
+			break;
+			}
+		default:
+			{
+			// Unknown error. For safety's sake let's disconnect a2dp link and inform btaudioman
+			TRACE_INFO((_L("CBtsacStreaming::HandleGavdpErrorL() Unknown error, goes to listening")))
+			Parent().CompletePendingRequests(KCompleteAllReqs, aError);
+			Parent().ChangeStateL(CBtsacListening::NewL(Parent(), EGavdpResetReasonGeneral, KErrDisconnected));
+			break;
+			}
+		}
+	}
+	
+//  End of File