diff -r d5f04de580b7 -r b74061f7f3d2 devsound/a3fdevsound/src/mmfdevsoundserver/mmfdevsoundsession.cpp --- a/devsound/a3fdevsound/src/mmfdevsoundserver/mmfdevsoundsession.cpp Wed Mar 31 23:56:23 2010 +0300 +++ b/devsound/a3fdevsound/src/mmfdevsoundserver/mmfdevsoundsession.cpp Wed Apr 14 17:32:53 2010 +0300 @@ -26,15 +26,15 @@ #define SYMBIAN_DEBPRN0(str) RDebug::Print(str, this) #define SYMBIAN_DEBPRN1(str, val1) RDebug::Print(str, this, val1) #define SYMBIAN_DEBPRN2(str, val1, val2) RDebug::Print(str, this, val1, val2) +#define SYMBIAN_DEBPRN3(str, val1, val2, val3) RDebug::Print(str, this, val1, val2, val3) #else #define SYMBIAN_DEBPRN0(str) #define SYMBIAN_DEBPRN1(str, val1) #define SYMBIAN_DEBPRN2(str, val1, val2) +#define SYMBIAN_DEBPRN3(str, val1, val2, val3) #endif //_DEBUG -//Assume that we can have two user request and one callback request -//at the same time (maximum). -const TInt KMaxQueueRequest = 3; +const TInt KMaxQueueRequest = 6; // MEMBER FUNCTIONS @@ -222,15 +222,23 @@ } // +// NeedToQueue - mid-commit cycle or async queue start AO is active +// +TBool CMMFDevSoundSession::NeedToQueue() const + { + return iOperationCompletePending || iAsyncQueueStart->IsActive(); + } + +// // CMMFDevSoundSession::ServiceL // (other items were commented in a header). // void CMMFDevSoundSession::ServiceL(const RMmfIpcMessage& aMessage) { SYMBIAN_DEBPRN2(_L("\nCMMFDevSoundSession[0x%x] NEW REQUEST %02x while pending=%d"), - aMessage.Function(), iOperationCompletePending || iAsyncQueueStart->IsActive()); + aMessage.Function(), NeedToQueue()); - if( iOperationCompletePending || iAsyncQueueStart->IsActive()) + if(NeedToQueue()) { // if not possible to service now, then queue request EnqueueRequest(aMessage); @@ -257,8 +265,11 @@ // void CMMFDevSoundSession::DoServiceRequestL(const RMmfIpcMessage& aMessage) { + iRequestBeingServiced.SetMessage(aMessage); iAsyncQueueStart->Cancel(); // just in case. - TMMFMessageDestinationPckg destinationPckg; + ResetNotifiedError(); + + TMMFMessageDestinationPckg destinationPckg; MmfMessageUtil::ReadL(aMessage, 0, destinationPckg); SYMBIAN_DEBPRN2(_L("CMMFDevSoundSession[0x%x]::DoServiceRequestL - DestinationHandle [%d] InterfaceId [%d] "), destinationPckg().DestinationHandle(), destinationPckg().InterfaceId()); if ((destinationPckg().DestinationHandle() == KMMFObjectHandleDevSound) && @@ -440,17 +451,29 @@ // Complete the message // Synchronous requests & Pseudo-asynchronous aMessage.Complete(KErrNone); - } - // Note: There are operations that not complete the message using the following flag - // So if the message is not completed, cannot be assumed that there is an operation pending - - SYMBIAN_DEBPRN1(_L("CMMFDevSoundSession[0x%x]::DoServiceRequestL - iOperationCompletePending [%d]"), iOperationCompletePending); - if(iOperationCompletePending) - { - // Keep a copy of the message for Asynchronous requests & Pseudo-asynchronous - iRequestBeingServiced.SetMessage(aMessage); + + // Store function if we need to re-apply it again due to pre-emption clash + if(iRequestBeingServiced.Type() == TMMFDevSoundRequest::EAction_PseudoAsynchronous) + { + iRedoFunction = aMessage.Function(); + } } } + else if (aMessage.Function() == RMessage2::EDisConnect) + { + TBool complete = iAdapter->CloseDevSound(); + if(!complete) + { + iRequestBeingServiced.SetMessage(aMessage); + iOperationCompletePending = ETrue; + ResetNotifiedError(); + } + else + { + // if we get here, iClosing wait will have been started and we'd be waiting + iClosingWait->AsyncStop(); + } + } else { // If there's a CI extension, see if that handles this request @@ -467,6 +490,7 @@ } iOperationCompletePending = EFalse; iHandlingExtdCI = EFalse; + SYMBIAN_DEBPRN2(_L("CMMFDevSoundSession[0x%x]::DoServiceRequestL - CIExtensionRequest[%d] - Exit with Error[%d] "), aMessage.Function(),err); } if (err != KErrNone) @@ -477,6 +501,80 @@ } } +void CMMFDevSoundSession::DoServiceAlreadyCompletedRequestL(const TInt aFunction) + { + ResetNotifiedError(); + + switch(aFunction) + { + case EMMFDevSoundProxyInitialize1: + DoAlreadyCompletedInitialize1L(); + break; + case EMMFDevSoundProxyInitialize2: + DoAlreadyCompletedInitialize2L(); + break; + case EMMFDevSoundProxyInitialize4: + DoAlreadyCompletedInitialize4L(); + break; + case EMMFDevSoundProxyPlayInit: + DoAlreadyCompletedPlayInitL(); + break; + case EMMFDevSoundProxyRecordInit: + DoAlreadyCompletedRecordInitL(); + break; + case EMMFDevSoundProxyPlayTone: + DoAlreadyCompletedPlayToneL(); + break; + case EMMFDevSoundProxyPlayDualTone: + DoAlreadyCompletedPlayDualToneL(); + break; + case EMMFDevSoundProxyPlayDTMFString: + DoAlreadyCompletedPlayDTMFStringL(); + break; + case EMMFDevSoundProxyPlayToneSequence: + DoAlreadyCompletedPlayToneSequenceL(); + break; + case EMMFDevSoundProxyPlayFixedSequence: + DoAlreadyCompletedPlayFixedSequenceL(); + break; + default: + User::Leave(KErrNotSupported); + break; + } + + } + +void CMMFDevSoundSession::HandleAlreadyCompletedRequest() + { + TRAPD(err,DoServiceAlreadyCompletedRequestL(iRedoFunction)); + + if (err != KErrNone) + { + switch(iRedoFunction) + { + case EMMFDevSoundProxyInitialize1: + case EMMFDevSoundProxyInitialize2: + case EMMFDevSoundProxyInitialize4: + InitializeComplete(err); + break; + case EMMFDevSoundProxyPlayInit: + PlayError(err); + break; + case EMMFDevSoundProxyRecordInit: + RecordError(err); + break; + case EMMFDevSoundProxyPlayTone: + case EMMFDevSoundProxyPlayDualTone: + case EMMFDevSoundProxyPlayDTMFString: + case EMMFDevSoundProxyPlayToneSequence: + case EMMFDevSoundProxyPlayFixedSequence: + ToneFinished(err); + break; + default: + break; + } + } + } void CMMFDevSoundSession::EnqueueRequest(const RMmfIpcMessage& aMessage) { @@ -510,6 +608,7 @@ DoSetClientConfigL();// added here instead of the CreateL() TMMFDevSoundProxySettingsPckg devSoundBuf; MmfMessageUtil::ReadL(aMessage,1,devSoundBuf); + iCachedClientData = devSoundBuf; TMMFState mode = devSoundBuf().iMode; iAdapter->InitializeL(mode); iBufferPlay = NULL; @@ -521,6 +620,20 @@ } // +// CMMFDevSoundSession::DoAlreadyCompletedInitialize1L +// (other items were commented in a header). +// +void CMMFDevSoundSession::DoAlreadyCompletedInitialize1L() + { + TMMFState mode = iCachedClientData().iMode; + iAdapter->InitializeL(mode); + iBufferPlay = NULL; + iPlayErrorOccured = EFalse; + // Flag to queue any further request + iOperationCompletePending = ETrue; + } + +// // CMMFDevSoundSession::DoInitialize2L // (other items were commented in a header). // @@ -532,6 +645,7 @@ DoSetClientConfigL();// added here instead of the CreateL() TMMFDevSoundProxySettingsPckg devSoundBuf; MmfMessageUtil::ReadL(aMessage,1,devSoundBuf); + iCachedClientData = devSoundBuf; TUid HWDev = devSoundBuf().iHWDev; TMMFState mode = devSoundBuf().iMode; iAdapter->InitializeL(HWDev, mode); @@ -541,6 +655,19 @@ } // +// CMMFDevSoundSession::DoAlreadyCompletedInitialize2L +// (other items were commented in a header). +// +void CMMFDevSoundSession::DoAlreadyCompletedInitialize2L() + { + TUid HWDev = iCachedClientData().iHWDev; + TMMFState mode = iCachedClientData().iMode; + iAdapter->InitializeL(HWDev, mode); + iBufferPlay = NULL; + iPlayErrorOccured = EFalse; + } + +// // CMMFDevSoundSession::DoInitialize4L // (other items were commented in a header). // @@ -552,6 +679,7 @@ DoSetClientConfigL();// added here instead of the CreateL() TMMFDevSoundProxySettingsPckg devSoundBuf; aMessage.ReadL(TInt(1),devSoundBuf); + iCachedClientData = devSoundBuf; TFourCC desiredFourCC = devSoundBuf().iDesiredFourCC; TMMFState mode = devSoundBuf().iMode; iAdapter->InitializeL(desiredFourCC, mode); @@ -564,6 +692,21 @@ } // +// CMMFDevSoundSession::DoAlreadyCompletedInitialize4L +// (other items were commented in a header). +// +void CMMFDevSoundSession::DoAlreadyCompletedInitialize4L() + { + TFourCC desiredFourCC = iCachedClientData().iDesiredFourCC; + TMMFState mode = iCachedClientData().iMode; + iAdapter->InitializeL(desiredFourCC, mode); + iBufferPlay = NULL; + iPlayErrorOccured = EFalse; + // Flag to queue any further request + iOperationCompletePending = ETrue; + } + +// // CMMFDevSoundSession::DoCancelInitialize // (other items were commented in a header). // @@ -782,6 +925,16 @@ } // +// CMMFDevSoundSession::DoAlreadyCompletedPlayInitL +// (other items were commented in a header). +// +void CMMFDevSoundSession::DoAlreadyCompletedPlayInitL() + { + iAdapter->PlayInitL(); + iOperationCompletePending = ETrue; + } + +// // CMMFDevSoundSession::DoRecordInitL // (other items were commented in a header). // @@ -793,6 +946,16 @@ } // +// CMMFDevSoundSession::DoAlreadyCompletedRecordInitL +// (other items were commented in a header). +// +void CMMFDevSoundSession::DoAlreadyCompletedRecordInitL() + { + iAdapter->RecordInitL(); + iOperationCompletePending = ETrue; + } + +// // CMMFDevSoundSession::DoPlayDataL // (other items were commented in a header). // @@ -868,6 +1031,7 @@ SYMBIAN_DEBPRN0(_L("CMMFDevSoundSession[0x%x]::DoPlayToneL - Enter")); TMMFDevSoundProxySettingsPckg devSoundBuf; aMessage.ReadL(TInt(1),devSoundBuf); + iCachedClientData = devSoundBuf; TInt frequency = devSoundBuf().iFrequencyOne; TTimeIntervalMicroSeconds duration(devSoundBuf().iDuration); iAdapter->PlayToneL(frequency, duration); @@ -877,6 +1041,18 @@ } // +// CMMFDevSoundSession::DoAlreadyCompletedPlayToneL +// (other items were commented in a header). +// +void CMMFDevSoundSession::DoAlreadyCompletedPlayToneL() + { + TInt frequency = iCachedClientData().iFrequencyOne; + TTimeIntervalMicroSeconds duration(iCachedClientData().iDuration); + iAdapter->PlayToneL(frequency, duration); + iOperationCompletePending = ETrue; + } + +// // CMMFDevSoundSession::DoPlayDualToneL // (other items were commented in a header). // @@ -885,6 +1061,7 @@ SYMBIAN_DEBPRN0(_L("CMMFDevSoundSession[0x%x]::DoPlayDualToneL - Enter")); TMMFDevSoundProxySettingsPckg devSoundBuf; aMessage.ReadL(TInt(1),devSoundBuf); + iCachedClientData = devSoundBuf; TInt frequencyOne = devSoundBuf().iFrequencyOne; TInt frequencyTwo = devSoundBuf().iFrequencyTwo; TTimeIntervalMicroSeconds duration(devSoundBuf().iDuration); @@ -895,6 +1072,19 @@ } // +// CMMFDevSoundSession::DoAlreadyCompletedPlayDualToneL +// (other items were commented in a header). +// +void CMMFDevSoundSession::DoAlreadyCompletedPlayDualToneL() + { + TInt frequencyOne = iCachedClientData().iFrequencyOne; + TInt frequencyTwo = iCachedClientData().iFrequencyTwo; + TTimeIntervalMicroSeconds duration(iCachedClientData().iDuration); + iAdapter->PlayDualToneL(frequencyOne, frequencyTwo, duration); + iOperationCompletePending = ETrue; + } + +// // CMMFDevSoundSession::DoPlayDTMFStringL // (other items were commented in a header). // @@ -920,6 +1110,16 @@ } // +// CMMFDevSoundSession::DoAlreadyCompletedPlayDTMFStringL +// (other items were commented in a header). +// +void CMMFDevSoundSession::DoAlreadyCompletedPlayDTMFStringL() + { + iAdapter->PlayDTMFStringL(*iDtmfString); + iOperationCompletePending = ETrue; + } + +// // CMMFDevSoundSession::DoPlayToneSequenceL // (other items were commented in a header). // @@ -945,6 +1145,16 @@ } // +// CMMFDevSoundSession::DoAlreadyCompletedPlayToneSequenceL +// (other items were commented in a header). +// +void CMMFDevSoundSession::DoAlreadyCompletedPlayToneSequenceL() + { + iAdapter->PlayToneSequenceL(*iToneSeqBuf); + iOperationCompletePending = ETrue; + } + +// // CMMFDevSoundSession::DoPlayFixedSequenceL // (other items were commented in a header). // @@ -954,7 +1164,7 @@ TPckgBuf buf; aMessage.ReadL(TInt(1),buf); TInt seqNum = buf(); - + iSeqNum = seqNum; iAdapter->PlayFixedSequenceL(seqNum); iOperationCompletePending = ETrue; SYMBIAN_DEBPRN1(_L("CMMFDevSoundSession[0x%x]::DoPlayFixedSequenceL - Exit. Return value is [%d]"), ETrue); @@ -962,6 +1172,16 @@ } // +// CMMFDevSoundSession::DoAlreadyCompletedPlayFixedSequenceL +// (other items were commented in a header). +// +void CMMFDevSoundSession::DoAlreadyCompletedPlayFixedSequenceL() + { + iAdapter->PlayFixedSequenceL(iSeqNum); + iOperationCompletePending = ETrue; + } + +// // CMMFDevSoundSession::DoSetDTMFLengthsL // (other items were commented in a header). // @@ -990,7 +1210,7 @@ TTimeIntervalMicroSeconds duration = devSoundBuf().iDuration; User::LeaveIfError(iAdapter->SetVolumeRamp(duration)); iOperationCompletePending = EFalse; // Volume ramp doesn't result on commit - SYMBIAN_DEBPRN0(_L("CMMFDevSoundSession[0x%x]::DoSetVolumeRampL - Exit")); + SYMBIAN_DEBPRN1(_L("CMMFDevSoundSession[0x%x]::DoSetVolumeRampL - Exit. Return value is [%d]"), ETrue); return ETrue; // operation complete } @@ -1075,7 +1295,7 @@ TPckgBuf repeatTS; aMessage.ReadL(TInt(2),repeatTS); User::LeaveIfError(iAdapter->SetToneRepeats(countRepeat(), repeatTS())); - SYMBIAN_DEBPRN0(_L("CMMFDevSoundSession[0x%x]::DoSetToneRepeatsL - Exit")); + SYMBIAN_DEBPRN1(_L("CMMFDevSoundSession[0x%x]::DoSetToneRepeatsL - Exit. Return value is [%d]"), ETrue); return ETrue; } @@ -1107,7 +1327,7 @@ fixSeqCountPckg = fixSeqCount; aMessage.WriteL(TInt(2),fixSeqCountPckg); - SYMBIAN_DEBPRN0(_L("CMMFDevSoundSession[0x%x]::DoFixedSequenceCountL - Exit")); + SYMBIAN_DEBPRN1(_L("CMMFDevSoundSession[0x%x]::DoFixedSequenceCountL - Exit. Return value is [%d]"), ETrue); return ETrue; } @@ -1420,13 +1640,25 @@ void CMMFDevSoundSession::Disconnect(const RMessage2& aMessage) { SYMBIAN_DEBPRN0(_L("CMMFDevSoundSession[0x%x]::Disconnect - Enter")); - TBool complete = iAdapter->CloseDevSound(); - if(!complete) - { - iRequestBeingServiced.SetMessage(aMessage); - iOperationCompletePending = ETrue; - iClosingWait->Start(); - } + if (NeedToQueue()) + { + // if we are in the middle of something, enqueue and wait + SYMBIAN_DEBPRN0(_L("CMMFDevSoundSession[0x%x]::Disconnect - Add to queue")); + EnqueueRequest(aMessage); + iClosingWait->Start(); + } + else + { + // else do now. Enter ActiveSchedulerWait to wait for AsyncOpComplete + TBool complete = iAdapter->CloseDevSound(); + if(!complete) + { + iRequestBeingServiced.SetMessage(aMessage); + iOperationCompletePending = ETrue; + ResetNotifiedError(); + iClosingWait->Start(); + } + } CSession2::Disconnect(aMessage); SYMBIAN_DEBPRN0(_L("CMMFDevSoundSession[0x%x]::Disconnect - Exit")); } @@ -1683,7 +1915,7 @@ // void CMMFDevSoundSession::CallbackFromAdaptorReceived(TInt aType, TInt aError) { - SYMBIAN_DEBPRN2(_L("CMMFDevSoundSession[0x%x]::CallbackFromAdaptorReceived - Enter. Type [%d ]Error [%d]"), aType, aError); + SYMBIAN_DEBPRN2(_L("CMMFDevSoundSession[0x%x]::CallbackFromAdaptorReceived - Enter. Type[%d] Error[%d]"), aType, aError); if(aType == KCallbackRecordPauseComplete) { TMMFDevSoundQueueItem item; @@ -1702,12 +1934,17 @@ } else if (aType == KCallbackFlushComplete) { - iRequestBeingServiced.Complete(aError); - iOperationCompletePending = EFalse; + if(!iHandlingExtdCI && iRequestBeingServiced.Function()==EMMFDevSoundProxyEmptyBuffers) + { + //If we come here then it is due to a EMMFDevSoundProxyEmptyBuffers request from client. + SYMBIAN_DEBPRN0(_L("CMMFDevSoundSession[0x%x]::CallbackFromAdaptorReceived - Calling TMMFDevSoundRequest::Complete on iRequestBeingServiced")); + iRequestBeingServiced.Complete(aError); + iOperationCompletePending = EFalse; + } } else { - if( iOperationCompletePending ) + if( NeedToQueue() ) { // If not possible to service now, then queue request // Encapsule the request @@ -1766,6 +2003,33 @@ } // +// CMMFDevSoundSession::PreemptionClash +// (other items were commented in a header). +// +void CMMFDevSoundSession::PreemptionClash() + { + //assumes sufficient space in the queue so ignore the return value + iQueuedRequests.Insert(iRequestBeingServiced, 0); + iPreemptionClash=ETrue; + } + +// +// CMMFDevSoundSession::PreemptionClashWithStateChange +// (other items were commented in a header). +// +void CMMFDevSoundSession::PreemptionClashWithStateChange() + { + #ifdef _DEBUG + TMMFDevSoundRequest msg = iQueuedRequests[0]; + // message being removed should be the one we previously pushed via PreemptionClash() + __ASSERT_DEBUG(iRequestBeingServiced==msg, Panic(ERequestBeingServicedMismatch)); + #endif + // remove without processing request with AsynchronousOperationComplete() completing the message + iQueuedRequests.Remove(0); + iPreemptionClash=EFalse; + } + +// // CMMFDevSoundSession::AdaptorControlsContext() // @@ -1812,6 +2076,13 @@ __ASSERT_DEBUG(!iHandlingExtdCI, Panic(EUnexpectedAsyncOpCompleteHandlingCI)); // when handling CIs we should not reach here + TInt error = aError; + if (!error) + { + // if have no error payload, use notified error. It will be KErrNone if not set, so just use. + error = NotifiedError(); + } + switch (iRequestBeingServiced.Type()) { case TMMFDevSoundRequest::ESessionEvents: @@ -1853,7 +2124,7 @@ FlushEventQueue(); } - iRequestBeingServiced.Complete(aError); + iRequestBeingServiced.Complete(error); iOperationCompletePending = EFalse; } } @@ -1881,9 +2152,19 @@ default: break; } + + if(iRequestBeingServiced.Type() == TMMFDevSoundRequest::ECallBackType ) + { + SYMBIAN_DEBPRN2(_L("CMMFDevSoundSession[0x%x] AsynchronousOperationComplete CallbackPF=%d pending=%d"), + iRequestBeingServiced.IsCallBack(), iOperationCompletePending ); + } + else + { + SYMBIAN_DEBPRN3(_L("CMMFDevSoundSession[0x%x] AsynchronousOperationComplete %x pending=%d Requestype=%d"), + iRequestBeingServiced.Function(), iOperationCompletePending, iRequestBeingServiced.Type() ); + } - SYMBIAN_DEBPRN2(_L("CMMFDevSoundSession[0x%x] AsynchronousOperationComplete %x pending=%d"),iRequestBeingServiced.Function(), iOperationCompletePending ); - + if ( aCanStartNewOperation && iQueuedRequests.Count() != 0 ) { DequeueRequest(); @@ -1939,11 +2220,29 @@ SYMBIAN_DEBPRN0(_L("\n CMMFDevSoundSession[0x%x]======== Service a queued request\n")); TMMFDevSoundRequest msg = iQueuedRequests[0]; iQueuedRequests.Remove(0); - TRAPD(err,DoServiceRequestL(msg.Message())); - if(err != KErrNone) - { - msg.Complete(err); - } + TInt err = KErrNone; + TBool doRequest = ETrue; + if(iPreemptionClash) + { + SYMBIAN_DEBPRN0(_L("CMMFDevSoundSession[0x%x]::AsyncQueueStartCallback - Re-applying client request due to Pre-emption clash")); + iPreemptionClash=EFalse; // clear flag before reading next request in queue + iAdapter->RollbackAdaptorActiveStateToBeforeCommit(); + if ((iRequestBeingServiced.Type() == TMMFDevSoundRequest::EAction_PseudoAsynchronous)) + { + doRequest = EFalse; + HandleAlreadyCompletedRequest(); + } + } + + if (doRequest) + { + TRAP(err,DoServiceRequestL(msg.Message())); + if(err != KErrNone) + { + msg.Complete(err); + } + } + if (!iOperationCompletePending && iQueuedRequests.Count() != 0) { //dequeue next @@ -1972,6 +2271,8 @@ // void CMMFDevSoundSession::DoProcessingFinished() { + ResetNotifiedError(); + TBool asyncOperation = EFalse; //ProcessingFinished should never fail __ASSERT_ALWAYS(KErrNone, iAdapter->ProcessingFinishedReceived(asyncOperation)); @@ -1987,6 +2288,8 @@ // void CMMFDevSoundSession::DoProcessingError() { + ResetNotifiedError(); + TBool asyncOperation = EFalse; //ProcessingFinished should never fail __ASSERT_ALWAYS(KErrNone, iAdapter->ProcessingError(asyncOperation)); @@ -2327,4 +2630,26 @@ // this will generate an processing error event and callback iAdapter->BufferErrorEvent(); } + +void CMMFDevSoundSession::ResetNotifiedError() +// called at beginning of commit cycle, so any error will be from callbacks + { + SYMBIAN_DEBPRN0(_L("CMMFDevSoundSession[0x%x]::ResetNotifiedError")); + iNotifiedError = KErrNone; + } + +TInt CMMFDevSoundSession::NotifiedError() const +// NotifiedError property + { + SYMBIAN_DEBPRN1(_L("CMMFDevSoundSession[0x%x]::NotifiedError(%d)"), iNotifiedError); + return iNotifiedError; + } + +void CMMFDevSoundSession::NotifyError(TInt aError) +// cache notified error + { + SYMBIAN_DEBPRN1(_L("CMMFDevSoundSession[0x%x]::NotifyError(%d)"), aError); + iNotifiedError = aError; + } + // End of file