diff -r 000000000000 -r f63038272f30 bluetoothengine/btsac/src/btsacStateStreaming.cpp --- /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