// Copyright (c) 2006-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 <s32mem.h>
#include "mmfaudioclientserver.h"
#include "mmfaudioserver.h"
#include "mmfdevsoundserver.h"
#include "mmfdevsoundsession.h"
#include <mmf/plugin/mmfdevsoundcustominterface.hrh>
#include <mm/mmpluginutils.h>
#ifdef _DEBUG
#include "e32debug.h"
#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
const TInt KMaxQueueRequest = 6;
// MEMBER FUNCTIONS
TMMFDevSoundRequest::TMMFDevSoundRequest()
: iMessageCompleted(EFalse),
iRequestType(EUndefinedType),
iCallBackPF(KCallbackNone)
{
}
TMMFDevSoundRequest::TMMFDevSoundRequest(TInt aIsCallBack)
: iMessageCompleted(EFalse),
iRequestType(ECallBackType),
iCallBackPF(aIsCallBack)
{
}
TMMFDevSoundRequest::TMMFDevSoundRequest(const TMMFDevSoundRequest& aRequest)
: iMessageCompleted(EFalse),
iMessage(aRequest.iMessage),
iCallBackPF(aRequest.iCallBackPF)
{
iRequestType = ResolveType();
}
TBool TMMFDevSoundRequest::operator==(const TMMFDevSoundRequest& aRequest) const
{
TBool retval = EFalse;
if ( aRequest.Function() == Function() )
{
retval = ETrue;
}
else
{
retval = EFalse;
}
return retval;
}
const RMmfIpcMessage& TMMFDevSoundRequest::Message()
{
return iMessage;
}
void TMMFDevSoundRequest::SetMessage(const RMmfIpcMessage& aMessage)
{
iMessageCompleted = EFalse;
iMessage = aMessage;
iRequestType = ResolveType();
}
void TMMFDevSoundRequest::SetMessageCallback()
{
iMessageCompleted = EFalse;
iRequestType = ECallBackType;
}
TInt TMMFDevSoundRequest::IsCallBack() const
{
return iCallBackPF;
}
TMMFDevSoundRequest::TA3FDevSoundRequestType TMMFDevSoundRequest::ResolveType()
{
TA3FDevSoundRequestType type = EUndefinedType;
switch(iMessage.Function())
{
case EMMFDevSoundProxyInitialize1:
case EMMFDevSoundProxyInitialize2:
case EMMFDevSoundProxyInitialize4:
case EMMFDevSoundProxyPlayInit:
case EMMFDevSoundProxyRecordInit:
case EMMFDevSoundProxyPlayTone:
case EMMFDevSoundProxyPlayDualTone:
case EMMFDevSoundProxyPlayDTMFString:
case EMMFDevSoundProxyPlayToneSequence:
case EMMFDevSoundProxyPlayFixedSequence:
type = EAction_PseudoAsynchronous;
break;
case EMMFDevSoundProxyStop:
case EMMFDevSoundProxyPause:
case EMMFDevSoundProxyClose:
case EMMFDevSoundProxyCancelInitialize:
case EMMFDevSoundProxyResume:
case EMMFDevSoundProxyEmptyBuffers:
type = EAction_Asynchronous;
break;
case EMMFDevSoundProxySetConfig:
case EMMFDevSoundProxyPostOpen: // Although this is not a configure operation technically, it has same calling pattern.
case EMMFDevSoundProxySetVolume:
case EMMFDevSoundProxySetGain:
case EMMFDevSoundProxySetPlayBalance:
case EMMFDevSoundProxySetRecordBalance:
case EMMFDevSoundProxySetVolumeRamp:
case EMMFDevSoundProxySetPrioritySettings:
type = EConfigure_Asynchronous;
break;
case EMMFDevSoundProxySetDTMFLengths:
case EMMFDevSoundProxySetToneRepeats:
type = EConfigure_Synchronous;
break;
case EMMFDevSoundProxyCapabilities:
type = EQuery_Asynchronous;
break;
case EMMFDevSoundProxyMaxVolume:
case EMMFDevSoundProxyMaxGain:
case EMMFDevSoundProxyConfig:
case EMMFDevSoundProxyVolume:
case EMMFDevSoundProxyGain:
case EMMFDevSoundProxyPlayBalance:
case EMMFDevSoundProxyRecordBalance:
case EMMFDevSoundProxyGetSupportedInputDataTypes:
case EMMFDevSoundProxyGetSupportedOutputDataTypes:
case EMMFDevSoundProxyFixedSequenceName:
case EMMFDevSoundProxyFixedSequenceCount:
case EMMFDevSoundProxySamplesRecorded:
case EMMFDevSoundProxySamplesPlayed:
case EMMFDevSoundProxyCopyFourCCArrayData:
case EMMFDevSoundProxyGetTimePlayed:
case EMMFDevSoundProxyIsResumeSupported:
type = EQuery_Synchronous;
break;
case EMMFDevSoundProxyBTBFData:
case EMMFDevSoundProxyBTBEData:
case EMMFDevSoundProxyPlayData:
case EMMFDevSoundProxyRecordData:
type = EBufferExchangeRelated;
break;
// Custom Interfaces
case EMMFDevSoundProxySyncCustomCommand:
case EMMFDevSoundProxySyncCustomCommandResult:
case EMMFDevSoundProxyAsyncCustomCommand:
case EMMFDevSoundProxyAsyncCustomCommandResult:
case EMMFDevSoundProxyCustomInterface:
type = ECustomInterfacesRelated;
break;
case RMessage2::EDisConnect:
type = ESessionEvents;
break;
default:
break;
}
return type;
}
void TMMFDevSoundRequest::Complete(TInt aError)
{
if(!iMessageCompleted && iRequestType != EUndefinedType && iRequestType != ECallBackType)
{
iMessage.Complete(aError);
iMessageCompleted = ETrue;
iRequestType = EUndefinedType;
}
}
TInt TMMFDevSoundRequest::Function() const
{
return iMessage.Function();
}
TMMFDevSoundRequest::TA3FDevSoundRequestType TMMFDevSoundRequest::Type() const
{
return iRequestType;
}
//
// CMMFDevSoundSession::CreateL
// Creates a new object
//
void CMMFDevSoundSession::CreateL(const CMmfIpcServer& aServer)
{
CMmfIpcSession::CreateL(aServer);
CMMFDevSoundServer& server =
const_cast<CMMFDevSoundServer&>(
static_cast<const CMMFDevSoundServer&>(aServer));
server.IncrementSessionId();
iDevSoundSessionId = server.DevSoundSessionId();
}
//
// 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(), NeedToQueue());
if(NeedToQueue())
{
// if not possible to service now, then queue request
EnqueueRequest(aMessage);
}
else
{
// If there is no oustanding operation service inmediately
TRAPD(err, DoServiceRequestL(aMessage));
if (err)
{
aMessage.Complete(err); // repeat normal ServiceL() behaviour since we may keep going
}
if (!iOperationCompletePending && iQueuedRequests.Count() != 0)
{
//dequeue next
DequeueRequest();
}
}
}
//
// CMMFDevSoundSession::DoServiceL
// (other items were commented in a header).
//
void CMMFDevSoundSession::DoServiceRequestL(const RMmfIpcMessage& aMessage)
{
iRequestBeingServiced.SetMessage(aMessage);
iAsyncQueueStart->Cancel(); // just in case.
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) &&
(destinationPckg().InterfaceId() == KUidInterfaceMMFDevSound))
{
SYMBIAN_DEBPRN1(_L("CMMFDevSoundSession[0x%x]::DoServiceRequestL - Request [%d]"), aMessage.Function());
TBool complete = EFalse;
switch(aMessage.Function())
{
case EMMFDevSoundProxyPostOpen:
complete = DoPostOpenL(aMessage);
break;
case EMMFDevSoundProxyInitialize1:
complete = DoInitialize1L(aMessage);
break;
case EMMFDevSoundProxyInitialize2:
complete = DoInitialize2L(aMessage);
break;
case EMMFDevSoundProxyInitialize4:
complete = DoInitialize4L(aMessage);
break;
case EMMFDevSoundProxyCapabilities:
complete = DoCapabilitiesL(aMessage);
break;
case EMMFDevSoundProxyConfig:
complete = DoConfigL(aMessage);
break;
case EMMFDevSoundProxySetConfig:
complete = DoSetConfigL(aMessage);
break;
case EMMFDevSoundProxyMaxVolume:
complete = DoMaxVolumeL(aMessage);
break;
case EMMFDevSoundProxyVolume:
complete = DoVolumeL(aMessage);
break;
case EMMFDevSoundProxySetVolume:
complete = DoSetVolumeL(aMessage);
break;
case EMMFDevSoundProxyMaxGain:
complete = DoMaxGainL(aMessage);
break;
case EMMFDevSoundProxyGain:
complete = DoGainL(aMessage);
break;
case EMMFDevSoundProxySetGain:
complete = DoSetGainL(aMessage);
break;
case EMMFDevSoundProxyPlayBalance:
complete = DoGetPlayBalanceL(aMessage);
break;
case EMMFDevSoundProxySetPlayBalance:
complete = DoSetPlayBalanceL(aMessage);
break;
case EMMFDevSoundProxyRecordBalance:
complete = DoGetRecordBalanceL(aMessage);
break;
case EMMFDevSoundProxySetRecordBalance:
complete = DoSetRecordBalanceL(aMessage);
break;
case EMMFDevSoundProxyBTBFData:
complete = DoBufferToBeFilledDataL(aMessage);
break;
case EMMFDevSoundProxyBTBEData:
complete = DoBufferToBeEmptiedDataL(aMessage);
break;
case EMMFDevSoundProxyPlayInit:
complete = DoPlayInitL(aMessage);
break;
case EMMFDevSoundProxyRecordInit:
complete = DoRecordInitL(aMessage);
break;
case EMMFDevSoundProxyPlayData:
complete = DoPlayDataL(aMessage);
break;
case EMMFDevSoundProxyRecordData:
complete = DoRecordDataL(aMessage);
break;
case EMMFDevSoundProxyStop:
complete = DoStopL(aMessage);
break;
case EMMFDevSoundProxyPause:
complete = DoPauseL(aMessage);
break;
case EMMFDevSoundProxyPlayTone:
complete = DoPlayToneL(aMessage);
break;
case EMMFDevSoundProxyPlayDualTone:
complete = DoPlayDualToneL(aMessage);
break;
case EMMFDevSoundProxyPlayDTMFString:
complete = DoPlayDTMFStringL(aMessage);
break;
case EMMFDevSoundProxyPlayToneSequence:
complete = DoPlayToneSequenceL(aMessage);
break;
case EMMFDevSoundProxyPlayFixedSequence:
complete = DoPlayFixedSequenceL(aMessage);
break;
case EMMFDevSoundProxySetDTMFLengths:
complete = DoSetDTMFLengthsL(aMessage);
break;
case EMMFDevSoundProxySetVolumeRamp:
complete = DoSetVolumeRampL(aMessage);
break;
case EMMFDevSoundProxyGetSupportedInputDataTypes:
complete = DoGetSupportedInputDataTypesL(aMessage);
break;
case EMMFDevSoundProxyGetSupportedOutputDataTypes:
complete = DoGetSupportedOutputDataTypesL(aMessage);
break;
case EMMFDevSoundProxyCopyFourCCArrayData:
complete = DoCopyFourCCArrayDataL(aMessage);
break;
case EMMFDevSoundProxySamplesRecorded:
complete = DoSamplesRecordedL(aMessage);
break;
case EMMFDevSoundProxySamplesPlayed:
complete = DoSamplesPlayedL(aMessage);
break;
case EMMFDevSoundProxySetToneRepeats:
complete = DoSetToneRepeatsL(aMessage);
break;
case EMMFDevSoundProxySetPrioritySettings:
complete = DoSetPrioritySettingsL(aMessage);
break;
case EMMFDevSoundProxyFixedSequenceCount:
complete = DoFixedSequenceCountL(aMessage);
break;
case EMMFDevSoundProxyCancelInitialize:
complete = DoCancelInitializeL(aMessage);
break;
case EMMFDevSoundProxyEmptyBuffers:
complete = DoEmptyBuffersL(aMessage);
break;
case EMMFDevSoundProxyGetTimePlayed:
complete = DoGetTimePlayedL(aMessage);
break;
case EMMFDevSoundProxyIsResumeSupported:
complete = DoQueryResumeSupportedL(aMessage);
break;
case EMMFDevSoundProxyResume:
complete = DoResumeL(aMessage);
break;
// DevSound custom command support
case EMMFDevSoundProxySyncCustomCommand:
case EMMFDevSoundProxySyncCustomCommandResult:
case EMMFDevSoundProxyAsyncCustomCommand:
case EMMFDevSoundProxyAsyncCustomCommandResult:
complete = DoCustomCommandL(aMessage);
break;
case EMMFDevSoundProxyClose:
complete = DoPrepareCloseL(aMessage);
break;
case EMMFDevSoundProxyRequestResourceNotification:
complete = DoRegisterAsClientL(aMessage);
break;
case EMMFDevSoundProxyCancelRequestResourceNotification:
complete = DoCancelRegisterAsClientL(aMessage);
break;
case EMMFDevSoundProxyGetResourceNotificationData:
complete = DoGetResourceNotificationDataL(aMessage);
break;
case EMMFDevSoundProxyWillResumePlay:
complete = DoWillResumePlayL(aMessage);
break;
case EMMFDevSoundProxySetClientThreadInfo:
complete = DoSetClientThreadInfoL(aMessage);
break;
default:
User::Leave(KErrNotSupported);
break;
}
// Check if can complete the message now
if (complete)
{
// Complete the message
// Synchronous requests & Pseudo-asynchronous
aMessage.Complete(KErrNone);
// 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
TInt err = KErrNotSupported;
if (iCIExtension)
{
SYMBIAN_DEBPRN1(_L("CMMFDevSoundSession[0x%x]::DoServiceRequestL - CIExtensionRequest [%d]"), aMessage.Function());
iOperationCompletePending = ETrue;
iHandlingExtdCI = ETrue;
TRAPD(err2, err = iCIExtension->HandleMessageL(aMessage));
if (err2)
{
err = err2;
}
iOperationCompletePending = EFalse;
iHandlingExtdCI = EFalse;
SYMBIAN_DEBPRN2(_L("CMMFDevSoundSession[0x%x]::DoServiceRequestL - CIExtensionRequest[%d] - Exit with Error[%d] "), aMessage.Function(),err);
}
if (err != KErrNone)
{
// Not been handled, the request is not supported
aMessage.Complete(KErrNotSupported);
}
}
}
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)
{
// Encapsule the request
TMMFDevSoundRequest request;
request.SetMessage(aMessage);
// Append
TInt error = iQueuedRequests.Append(request);
__ASSERT_DEBUG(error == KErrNone, Panic(EQueueRequestsFailedToAppend));
}
//
// CMMFDevSoundSession::DoPostOpenL
//
TBool CMMFDevSoundSession::DoPostOpenL(const RMmfIpcMessage& /*aMessage*/)
{
iAdapter->PostOpenL();
iOperationCompletePending = ETrue;
return EFalse;
}
//
// CMMFDevSoundSession::DoInitialize1L
// (other items were commented in a header).
//
TBool CMMFDevSoundSession::DoInitialize1L(const RMmfIpcMessage& aMessage)
{
iMsgQueue.Close(); // close if already open
TInt err = iMsgQueue.Open(aMessage, 2, EOwnerThread); // a global queue but owned by thread
User::LeaveIfError(err);
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;
iPlayErrorOccured = EFalse;
// Flag to queue any further request
// but the message can be completed now
iOperationCompletePending = ETrue;
return ETrue;
}
//
// 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).
//
TBool CMMFDevSoundSession::DoInitialize2L(const RMmfIpcMessage& aMessage)
{
iMsgQueue.Close(); // close if already open
TInt err = iMsgQueue.Open(aMessage, 2, EOwnerThread); // a global queue but owned by thread
User::LeaveIfError(err);
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);
iBufferPlay = NULL;
iPlayErrorOccured = EFalse;
return ETrue;
}
//
// 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).
//
TBool CMMFDevSoundSession::DoInitialize4L(const RMmfIpcMessage& aMessage)
{
iMsgQueue.Close();
TInt err = iMsgQueue.Open(aMessage, 2, EOwnerThread); // a global queue but owned by thread
User::LeaveIfError(err);
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);
iBufferPlay = NULL;
iPlayErrorOccured = EFalse;
// Flag to queue any further request
// but the message can be completed now
iOperationCompletePending = ETrue;
return ETrue;
}
//
// 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).
//
TBool CMMFDevSoundSession::DoCancelInitializeL(const RMmfIpcMessage& aMessage)
{
TInt err=iAdapter->CancelInitialize();
if (err != KErrNone)
{
aMessage.Complete(err);
iOperationCompletePending = EFalse;
return ETrue;
}
else
{
iOperationCompletePending = ETrue;
}
return EFalse;
}
//
// CMMFDevSoundSession::DoCapabilitiesL
// (other items were commented in a header).
//
TBool CMMFDevSoundSession::DoCapabilitiesL(const RMmfIpcMessage& aMessage)
{
TInt err = iAdapter->Capabilities(iDevSoundCapabilities);
if(err != KErrNone)
{
aMessage.Complete(err);
iOperationCompletePending = EFalse;
}
else
{
iOperationCompletePending = ETrue;
}
return EFalse;
}
//
// CMMFDevSoundSession::DoConfigL
// (other items were commented in a header).
//
TBool CMMFDevSoundSession::DoConfigL(const RMmfIpcMessage& aMessage)
{
TMMFDevSoundProxySettings devSoundSet;
devSoundSet.iConfig = iAdapter->Config();
TMMFDevSoundProxySettingsPckg pckg(devSoundSet);
aMessage.WriteL(TInt(2),pckg);
return ETrue;
}
//
// CMMFDevSoundSession::DoSetConfigL
// (other items were commented in a header).
//
TBool CMMFDevSoundSession::DoSetConfigL(const RMmfIpcMessage& aMessage)
{
TMMFDevSoundProxySettingsPckg devSoundBuf;
aMessage.ReadL(TInt(1),devSoundBuf);
TMMFCapabilities config = devSoundBuf().iConfig;
iAdapter->SetConfigL(config);
iOperationCompletePending = ETrue;
return EFalse;
}
//
// CMMFDevSoundSession::axVolumeL
// (other items were commented in a header).
//
TBool CMMFDevSoundSession::DoMaxVolumeL(const RMmfIpcMessage& aMessage)
{
TMMFDevSoundProxySettings devSoundSet;
devSoundSet.iMaxVolume = iAdapter->MaxVolume();
TMMFDevSoundProxySettingsPckg pckg(devSoundSet);
aMessage.WriteL(TInt(2),pckg);
return ETrue;
}
//
// CMMFDevSoundSession::DoVolumeL
// (other items were commented in a header).
//
TBool CMMFDevSoundSession::DoVolumeL(const RMmfIpcMessage& aMessage)
{
TMMFDevSoundProxySettings devSoundSet;
devSoundSet.iVolume = iAdapter->Volume();
TMMFDevSoundProxySettingsPckg pckg(devSoundSet);
aMessage.WriteL(TInt(2),pckg);
return ETrue;
}
//
// CMMFDevSoundSession::DoSetVolumeL
// (other items were commented in a header).
//
TBool CMMFDevSoundSession::DoSetVolumeL(const RMmfIpcMessage& aMessage)
{
TMMFDevSoundProxySettingsPckg devSoundBuf;
aMessage.ReadL(TInt(1),devSoundBuf);
TInt volume = devSoundBuf().iVolume;
TBool asyncOperation;
User::LeaveIfError(iAdapter->SetVolume(volume, asyncOperation));
iOperationCompletePending = asyncOperation;
return !asyncOperation;
}
//
// CMMFDevSoundSession::DoMaxGainL
// (other items were commented in a header).
//
TBool CMMFDevSoundSession::DoMaxGainL(const RMmfIpcMessage& aMessage)
{
TMMFDevSoundProxySettings devSoundSet;
devSoundSet.iMaxGain = iAdapter->MaxGain();
TMMFDevSoundProxySettingsPckg pckg(devSoundSet);
aMessage.WriteL(TInt(2),pckg);
return ETrue;
}
//
// CMMFDevSoundSession::DoGainL
// (other items were commented in a header).
//
TBool CMMFDevSoundSession::DoGainL(const RMmfIpcMessage& aMessage)
{
TMMFDevSoundProxySettings devSoundSet;
devSoundSet.iGain = iAdapter->Gain();
TMMFDevSoundProxySettingsPckg pckg(devSoundSet);
aMessage.WriteL(TInt(2),pckg);
return ETrue;
}
//
// CMMFDevSoundSession::DoSetGainL
// (other items were commented in a header).
//
TBool CMMFDevSoundSession::DoSetGainL(const RMmfIpcMessage& aMessage)
{
TMMFDevSoundProxySettingsPckg devSoundBuf;
aMessage.ReadL(TInt(1),devSoundBuf);
TInt gain = devSoundBuf().iGain;
TBool asyncOperation;
User::LeaveIfError(iAdapter->SetGain(gain, asyncOperation));
iOperationCompletePending = asyncOperation;
return !asyncOperation;
}
//
// CMMFDevSoundSession::DoGetPlayBalanceL
// (other items were commented in a header).
//
TBool CMMFDevSoundSession::DoGetPlayBalanceL(const RMmfIpcMessage& aMessage)
{
TMMFDevSoundProxySettings devSoundSet;
iAdapter->GetPlayBalanceL(devSoundSet.iLeftPercentage, devSoundSet.iRightPercentage);
TMMFDevSoundProxySettingsPckg pckg(devSoundSet);
aMessage.WriteL(TInt(2),pckg);
return ETrue;
}
//
// CMMFDevSoundSession::DoSetPlayBalanceL
// (other items were commented in a header).
//
TBool CMMFDevSoundSession::DoSetPlayBalanceL(const RMmfIpcMessage& aMessage)
{
TMMFDevSoundProxySettingsPckg devSoundBuf;
aMessage.ReadL(TInt(1),devSoundBuf);
TInt leftPercentage = devSoundBuf().iLeftPercentage;
TInt rightPercentage = devSoundBuf().iRightPercentage;
TBool asyncOperation;
iAdapter->SetPlayBalanceL(leftPercentage, rightPercentage, asyncOperation);
iOperationCompletePending = asyncOperation;
return !asyncOperation;
}
//
// CMMFDevSoundSession::DoGetRecordBalanceL
// (other items were commented in a header).
//
TBool CMMFDevSoundSession::DoGetRecordBalanceL(const RMmfIpcMessage& aMessage)
{
TMMFDevSoundProxySettings devSoundSet;
iAdapter->GetRecordBalanceL(devSoundSet.iLeftPercentage, devSoundSet.iRightPercentage);
TMMFDevSoundProxySettingsPckg pckg(devSoundSet);
aMessage.WriteL(TInt(2),pckg);
return ETrue;
}
//
// CMMFDevSoundSession::DoSetRecordBalanceL
// (other items were commented in a header).
//
TBool CMMFDevSoundSession::DoSetRecordBalanceL(const RMmfIpcMessage& aMessage)
{
TMMFDevSoundProxySettingsPckg devSoundBuf;
aMessage.ReadL(TInt(1),devSoundBuf);
TInt leftPercentage = devSoundBuf().iLeftPercentage;
TInt rightPercentage = devSoundBuf().iRightPercentage;
TBool asyncOperation;
iAdapter->SetRecordBalanceL(leftPercentage, rightPercentage, asyncOperation);
iOperationCompletePending = asyncOperation;
return !asyncOperation;
}
//
// CMMFDevSoundSession::DoPlayInitL
// (other items were commented in a header).
//
TBool CMMFDevSoundSession::DoPlayInitL(const RMmfIpcMessage& /*aMessage*/)
{
iAdapter->PlayInitL();
iOperationCompletePending = ETrue;
return ETrue;
}
//
// 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).
//
TBool CMMFDevSoundSession::DoRecordInitL(const RMmfIpcMessage& /*aMessage*/)
{
iAdapter->RecordInitL();
iOperationCompletePending = ETrue;
return ETrue;
}
//
// 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).
//
TBool CMMFDevSoundSession::DoPlayDataL(const RMmfIpcMessage& aMessage)
{
SYMBIAN_DEBPRN0(_L("CMMFDevSoundSession[0x%x]::DoPlayDataL - Enter"));
if( iPlayErrorOccured )
{
SYMBIAN_DEBPRN0(_L("CMMFDevSoundSession[0x%x]::DoPlayDataL - Ignore and Exit"));
return ETrue;
}
TMMFDevSoundProxyHwBufPckg devSoundBuf;
aMessage.ReadL(TInt(1),devSoundBuf);
iBufferPlay->SetLastBuffer(devSoundBuf().iLastBuffer);
TPtr8 dataPtr(iChunk.Base(), devSoundBuf().iBufferSize, devSoundBuf().iBufferSize);
// Copy data over from chunk
iBufferPlay->Data().Copy(dataPtr);
iAdapter->PlayData();
SYMBIAN_DEBPRN0(_L("CMMFDevSoundSession[0x%x]::DoPlayDataL - Exit"));
return ETrue;
}
//
// CMMFDevSoundSession::DoRecordDataL
// (other items were commented in a header).
//
TBool CMMFDevSoundSession::DoRecordDataL(const RMmfIpcMessage& /*aMessage*/)
{
iAdapter->RecordData();
return ETrue;
}
//
// CMMFDevSoundSession::DoStopL
// (other items were commented in a header).
//
TBool CMMFDevSoundSession::DoStopL(const RMmfIpcMessage& /*aMessage*/)
{
SYMBIAN_DEBPRN0(_L("CMMFDevSoundSession[0x%x]::DoStopL - Enter"));
// Sometimes Stop is not involved on a commit cycle
TBool completed = iAdapter->Stop();
if (completed)
{
iQueuedRequests.Reset();
FlushEventQueue(); // completed returned here means we were idle to start with. TODO could possibly skip this flush
iChunk.Close();
}
iOperationCompletePending = !completed;
SYMBIAN_DEBPRN1(_L("CMMFDevSoundSession[0x%x]::DoStopL - Exit. Return value is [%d]"), completed);
return completed;
}
//
// CMMFDevSoundSession::DoPauseL
// (other items were commented in a header).
//
TBool CMMFDevSoundSession::DoPauseL(const RMmfIpcMessage& /*aMessage*/)
{
User::LeaveIfError(iAdapter->Pause());
iOperationCompletePending = ETrue;
return EFalse;
}
//
// CMMFDevSoundSession::DoPlayToneL
// (other items were commented in a header).
//
TBool CMMFDevSoundSession::DoPlayToneL(const RMmfIpcMessage& aMessage)
{
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);
iOperationCompletePending = ETrue;
SYMBIAN_DEBPRN1(_L("CMMFDevSoundSession[0x%x]::DoPlayToneL - Exit. Return value is [%d]"), ETrue);
return ETrue;
}
//
// 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).
//
TBool CMMFDevSoundSession::DoPlayDualToneL(const RMmfIpcMessage& aMessage)
{
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);
iAdapter->PlayDualToneL(frequencyOne, frequencyTwo, duration);
iOperationCompletePending = ETrue;
SYMBIAN_DEBPRN1(_L("CMMFDevSoundSession[0x%x]::DoPlayDualToneL - Exit. Return value is [%d]"), ETrue);
return ETrue;
}
//
// 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).
//
TBool CMMFDevSoundSession::DoPlayDTMFStringL(const RMmfIpcMessage& aMessage)
{
SYMBIAN_DEBPRN0(_L("CMMFDevSoundSession[0x%x]::DoPlayDTMFStringL - Enter"));
TInt dtmfLength = aMessage.GetDesLength(2);
if(iDtmfString)
{
delete iDtmfString;
iDtmfString = NULL;
}
iDtmfString = HBufC::NewL(dtmfLength);
TPtr dtmfPtr = iDtmfString->Des();
aMessage.ReadL(TInt(2), dtmfPtr);
iAdapter->PlayDTMFStringL(*iDtmfString);
iOperationCompletePending = ETrue;
SYMBIAN_DEBPRN1(_L("CMMFDevSoundSession[0x%x]::DoPlayDTMFStringL - Exit. Return value is [%d]"), ETrue);
return ETrue;
}
//
// 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).
//
TBool CMMFDevSoundSession::DoPlayToneSequenceL(const RMmfIpcMessage& aMessage)
{
SYMBIAN_DEBPRN0(_L("CMMFDevSoundSession[0x%x]::DoPlayToneSequenceL - Enter"));
TInt toneLength = aMessage.GetDesLength(1);
if(iToneSeqBuf)
{
delete iToneSeqBuf;
iToneSeqBuf = NULL;
}
iToneSeqBuf = HBufC8::NewL(toneLength);
TPtr8 toneSeqPtr = iToneSeqBuf->Des();
aMessage.ReadL(TInt(1), toneSeqPtr);
iAdapter->PlayToneSequenceL(*iToneSeqBuf);
iOperationCompletePending = ETrue;
SYMBIAN_DEBPRN1(_L("CMMFDevSoundSession[0x%x]::DoPlayToneSequenceL - Exit. Return value is [%d]"), ETrue);
return ETrue;
}
//
// 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).
//
TBool CMMFDevSoundSession::DoPlayFixedSequenceL(const RMmfIpcMessage& aMessage)
{
SYMBIAN_DEBPRN0(_L("CMMFDevSoundSession[0x%x]::DoPlayFixedSequenceL - Enter"));
TPckgBuf<TInt> 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);
return ETrue;
}
//
// 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).
//
TBool CMMFDevSoundSession::DoSetDTMFLengthsL(const RMmfIpcMessage& aMessage)
{
SYMBIAN_DEBPRN0(_L("CMMFDevSoundSession[0x%x]::DoSetDTMFLengthsL - Enter"));
TMMFDevSoundProxySettingsPckg devSoundBuf;
aMessage.ReadL(TInt(1),devSoundBuf);
TTimeIntervalMicroSeconds32 toneOnLength = devSoundBuf().iToneOnLength;
TTimeIntervalMicroSeconds32 toneOffLength = devSoundBuf().iToneOffLength;
TTimeIntervalMicroSeconds32 pauseLength = devSoundBuf().iPauseLength;
User::LeaveIfError(iAdapter->SetDTMFLengths(toneOnLength, toneOffLength, pauseLength));
SYMBIAN_DEBPRN1(_L("CMMFDevSoundSession[0x%x]::DoSetDTMFLengthsL - Exit. Return value is [%d]"), ETrue);
return ETrue;
}
//
// CMMFDevSoundSession::DoSetVolumeRampL
// (other items were commented in a header).
//
TBool CMMFDevSoundSession::DoSetVolumeRampL(const RMmfIpcMessage& aMessage)
{
SYMBIAN_DEBPRN0(_L("CMMFDevSoundSession[0x%x]::DoSetVolumeRampL - Enter"));
TMMFDevSoundProxySettingsPckg devSoundBuf;
aMessage.ReadL(TInt(1),devSoundBuf);
TTimeIntervalMicroSeconds duration = devSoundBuf().iDuration;
User::LeaveIfError(iAdapter->SetVolumeRamp(duration));
iOperationCompletePending = EFalse; // Volume ramp doesn't result on commit
SYMBIAN_DEBPRN1(_L("CMMFDevSoundSession[0x%x]::DoSetVolumeRampL - Exit. Return value is [%d]"), ETrue);
return ETrue; // operation complete
}
//
// CMMFDevSoundSession::DoGetSupportedInputDataTypesL
// (other items were commented in a header).
//
TBool CMMFDevSoundSession::DoGetSupportedInputDataTypesL(
const RMmfIpcMessage& aMessage)
{
iArray.Reset();
TMMFPrioritySettingsPckg prioritySetBuf;
aMessage.ReadL(TInt(1),prioritySetBuf);
TMMFPrioritySettings prioritySet = prioritySetBuf();
iAdapter->GetSupportedInputDataTypesL(iArray, prioritySet);
TPckgBuf<TInt> pckg;
pckg() = iArray.Count();
aMessage.WriteL(TInt(2),pckg);
return ETrue;
}
//
// CMMFDevSoundSession::DoGetSupportedOutputDataTypesL
// (other items were commented in a header).
//
TBool CMMFDevSoundSession::DoGetSupportedOutputDataTypesL(
const RMmfIpcMessage& aMessage)
{
iArray.Reset();
TMMFPrioritySettingsPckg prioritySetBuf;
aMessage.ReadL(TInt(1),prioritySetBuf);
TMMFPrioritySettings prioritySet = prioritySetBuf();
iAdapter->GetSupportedOutputDataTypesL(iArray, prioritySet);
TPckgBuf<TInt> pckg;
pckg() = iArray.Count();
aMessage.WriteL(TInt(2),pckg);
return ETrue;
}
//
// CMMFDevSoundSession::DoSamplesRecordedL
// (other items were commented in a header).
//
TBool CMMFDevSoundSession::DoSamplesRecordedL(const RMmfIpcMessage& aMessage)
{
TPckgBuf<TInt> pckg;
pckg() = iAdapter->SamplesRecorded();
aMessage.WriteL(TInt(2),pckg);
return ETrue;
}
//
// CMMFDevSoundSession::DoSamplesPlayedL
// (other items were commented in a header).
//
TBool CMMFDevSoundSession::DoSamplesPlayedL(const RMmfIpcMessage& aMessage)
{
TPckgBuf<TInt> pckg;
pckg() = iAdapter->SamplesPlayed();
aMessage.WriteL(TInt(2),pckg);
return ETrue;
}
//
// CMMFDevSoundSession::DoSetToneRepeatsL
// (other items were commented in a header).
//
TBool CMMFDevSoundSession::DoSetToneRepeatsL(const RMmfIpcMessage& aMessage)
{
SYMBIAN_DEBPRN0(_L("CMMFDevSoundSession[0x%x]::DoSetToneRepeatsL - Enter"));
TPckgBuf<TInt> countRepeat;
aMessage.ReadL(TInt(1),countRepeat);
TPckgBuf<TTimeIntervalMicroSeconds> repeatTS;
aMessage.ReadL(TInt(2),repeatTS);
User::LeaveIfError(iAdapter->SetToneRepeats(countRepeat(), repeatTS()));
SYMBIAN_DEBPRN1(_L("CMMFDevSoundSession[0x%x]::DoSetToneRepeatsL - Exit. Return value is [%d]"), ETrue);
return ETrue;
}
//
// CMMFDevSoundSession::DoSetPrioritySettingsL
// (other items were commented in a header).
//
TBool CMMFDevSoundSession::DoSetPrioritySettingsL(
const RMmfIpcMessage& aMessage)
{
TPckgBuf<TMMFPrioritySettings> prioritySet;
aMessage.ReadL(TInt(1),prioritySet);
User::LeaveIfError(iAdapter->SetPrioritySettings(prioritySet()));
iOperationCompletePending = EFalse;
return ETrue;
}
//
// CMMFDevSoundSession::DoFixedSequenceCountL
// (other items were commented in a header).
//
TBool CMMFDevSoundSession::DoFixedSequenceCountL(
const RMmfIpcMessage& aMessage)
{
SYMBIAN_DEBPRN0(_L("CMMFDevSoundSession[0x%x]::DoFixedSequenceCountL - Enter"));
TPckgBuf<TInt> fixSeqCountPckg;
TInt fixSeqCount = iAdapter->FixedSequenceCount();
fixSeqCountPckg = fixSeqCount;
aMessage.WriteL(TInt(2),fixSeqCountPckg);
SYMBIAN_DEBPRN1(_L("CMMFDevSoundSession[0x%x]::DoFixedSequenceCountL - Exit. Return value is [%d]"), ETrue);
return ETrue;
}
//
// CMMFDevSoundSession::DoCopyFourCCArrayDataL
// (other items were commented in a header).
//
TBool CMMFDevSoundSession::DoCopyFourCCArrayDataL(
const RMmfIpcMessage& aMessage)
{
const TInt KBufExpandSize8 = 8;//two TInts
CBufFlat* dataCopyBuffer = CBufFlat::NewL(KBufExpandSize8);
CleanupStack::PushL(dataCopyBuffer);
RBufWriteStream stream;
stream.Open(*dataCopyBuffer);
CleanupClosePushL(stream);
TInt i = 0;
TInt count = iArray.Count();
while (i < count)
{
stream.WriteInt32L(iArray[i].FourCC());
i++;
}
aMessage.WriteL(TInt(2), dataCopyBuffer->Ptr(0));
stream.Close();
CleanupStack::PopAndDestroy(&stream);
CleanupStack::PopAndDestroy(dataCopyBuffer);
return ETrue;
}
//
// CMMFDevSoundSession::DoBufferToBeFilledDataL
// (other items were commented in a header).
//
TBool CMMFDevSoundSession::DoBufferToBeFilledDataL(
const RMmfIpcMessage& aMessage)
{
// if CMMFDevSoundSession::PlayError() has been called, RChunk would have got closed.
// Need to check if Chunk Handle is still valid. If it is not,complete the message immediately and send a error to the Client.
if(!iChunk.Handle())
{
aMessage.Complete(KErrBadHandle);
return EFalse;
}
TPckgBuf<TInt> requestChunkBuf;
MmfMessageUtil::Read(aMessage, TInt(1), requestChunkBuf);
TBool requestChunk = requestChunkBuf();
if (requestChunk)
{
// if the client requests, always do EOpen
iHwBufPckgFill().iChunkOp = EOpen;
}
TInt err = MmfMessageUtil::Write(aMessage, TInt(2), iHwBufPckgFill);
if ( (err == KErrNone) && (iHwBufPckgFill().iChunkOp == EOpen) )
{
aMessage.Complete(iChunk);
}
else
{
aMessage.Complete(err);
}
return EFalse;
}
// CMMFDevSoundSession::DoBufferToBeEmptiedDataL
// (other items were commented in a header).
//
TBool CMMFDevSoundSession::DoBufferToBeEmptiedDataL(
const RMmfIpcMessage& aMessage)
{
// if CMMFDevSoundSession::RecordError() has been called, RChunk would have got closed.
// Need to check if Chunk Handle is still valid. If it is not,complete the message immediately and send a error to the Client.
if(!iChunk.Handle())
{
aMessage.Complete(KErrBadHandle);
return EFalse;
}
TInt err = MmfMessageUtil::Write(aMessage, TInt(2), iHwBufPckgEmpty);
if ( (err == KErrNone) && (iHwBufPckgEmpty().iChunkOp == EOpen) )
{
aMessage.Complete(iChunk);
}
else
{
aMessage.Complete(err);
}
return EFalse;
}
//
// CMMFDevSoundSession::DoEmptyBuffersL
// (other items were commented in a header).
//
TBool CMMFDevSoundSession::DoEmptyBuffersL(const RMmfIpcMessage& aMessage)
{
TInt err = KErrNone;
FilterQueueEvent(EMMFDevSoundProxyBTBFEvent);
// This is now asynchronous
err = iAdapter->EmptyBuffers();
if (err != KErrNone)
{
aMessage.Complete(err);
return EFalse;
}
iOperationCompletePending = ETrue;
return EFalse;
}
//
// CMMFDevSoundSession::DoGetTimePlayedL
// (other items were commented in a header).
//
TBool CMMFDevSoundSession::DoGetTimePlayedL(const RMmfIpcMessage& aMessage)
{
TInt err = KErrNone;
TTimeIntervalMicroSeconds time(0);
TPckgBuf<TTimeIntervalMicroSeconds> timePckg(time);
err = iAdapter->GetTimePlayed(timePckg());
if (err != KErrNone)
{
aMessage.Complete(err);
return EFalse;
}
aMessage.WriteL(TInt(2),timePckg);
return ETrue;
}
TBool CMMFDevSoundSession::DoQueryResumeSupportedL(const RMmfIpcMessage& aMessage)
{
TBool isSupported = EFalse;
TPckgBuf<TBool> isSupportedPckg(isSupported);
isSupportedPckg() = iAdapter->IsResumeSupported();
aMessage.WriteL(TInt(2),isSupportedPckg);
return ETrue;
}
TBool CMMFDevSoundSession::DoResumeL(const RMmfIpcMessage& /*aMessage*/)
{
User::LeaveIfError( iAdapter->Resume() );
iOperationCompletePending = ETrue;
FilterQueueEvent(EMMFDevSoundProxyPausedRecordCompleteEvent);
return EFalse;
}
TBool CMMFDevSoundSession::DoPrepareCloseL(const RMmfIpcMessage& /*aMessage*/)
{
TBool complete = iAdapter->CloseDevSound();
if(!complete)
{
iOperationCompletePending = ETrue;
}
return complete;
}
TBool CMMFDevSoundSession::DoCustomCommandL(const RMmfIpcMessage& aMessage)
{
TInt retVal = KErrNone;
TRAPD(err, retVal = iDeMuxUtility->ProcessCustomInterfaceCommandL(aMessage));
if (err != KErrNone)
{
// the framework left with an error condition
// so we complete the message with this error
// irrespective of whether its a Sync or Async custom command
aMessage.Complete(err);
}
else
{
TInt messageType = aMessage.Function();
if ((messageType == EMMFDevSoundProxySyncCustomCommand) ||
(messageType == EMMFDevSoundProxySyncCustomCommandResult))
{
// If its a sync custom command
// we can pass back valid values here since command
// has been handled by the DeMux framework
aMessage.Complete(retVal);
}
}
// we complete our own message so don't need the framework to do so
return EFalse;
}
//
// CMMFDevSoundSession::CMMFDevSoundSession
// (other items were commented in a header).
//
CMMFDevSoundSession::CMMFDevSoundSession() :
iSetClientConfigApplied (EFalse)
{
}
//
// CMMFDevSoundSession::~CMMFDevSoundSession
// (other items were commented in a header).
//
CMMFDevSoundSession::~CMMFDevSoundSession()
{
delete iAsyncQueueStart;
// clear the array of custom interfaces
TInt count = iCustomInterfaceArray.Count();
for (TInt i = 0; i < count; i++)
{
// we could have already deleted interfaces without
// removing them from the array so check for this
// and only delete release plugin if non-null
MMMFDevSoundCustomInterfaceDeMuxPlugin* ptr = iCustomInterfaceArray[i].iInterface;
if (ptr)
{
iCustomInterfaceArray[i].iInterface->Release();
}
}
iCustomInterfaceArray.Reset();
iCustomInterfaceArray.Close();
delete iDeMuxUtility;
if (iCIExtension)
{
iCIExtension->Release();
iCIExtension = NULL;
}
iMsgQueue.Close();
iArray.Close();
iQueuedRequests.Close();
delete iDtmfString;
delete iToneSeqBuf;
delete iAdapter;
delete iClosingWait;
CMMFDevSoundServer* server =
const_cast<CMMFDevSoundServer*>(
static_cast<const CMMFDevSoundServer*>(Server()));
if (server)
{
server->DecrementSessionId();
}
// delete iCustomCommandParserManager;
// delete iMMFObjectContainer;
// Close chunk
iChunk.Close();
}
//
// CMMFDevSoundSession::FlushEventQueue()
//
void CMMFDevSoundSession::FlushEventQueue()
{
SYMBIAN_DEBPRN0(_L("CMMFDevSoundSession[0x%x]::FlushEventQueue - Enter"));
if(iMsgQueue.Handle() != 0)
{
TMMFDevSoundQueueItem queueItem;
TInt err = KErrNone;
while(err != KErrUnderflow)
{
err = iMsgQueue.Receive(queueItem);
}
}
SYMBIAN_DEBPRN0(_L("CMMFDevSoundSession[0x%x]::FlushEventQueue - Exit"));
}
void CMMFDevSoundSession::FilterQueueEvent(TMMFDevSoundProxyRequest aRequest)
{
SYMBIAN_DEBPRN0(_L("CMMFDevSoundSession[0x%x]::FilterQueueEvent - Enter"));
if(iMsgQueue.Handle() != 0)
{
// Pop and push events result at the queue
// can be seen as "circular list"
// set a mark to traverse it safely
TMMFDevSoundQueueItem markItem;
markItem.iRequest = EMMFDevSoundProxyMarkEvent;
// assumes sufficient space in the queue
TInt err = iMsgQueue.Send(markItem);
__ASSERT_DEBUG(err == KErrNone, Panic(EMsgQueueFailedToSendMsg));
while(ETrue)
{
// At least the markEvent is at the queue so ignore the error
TMMFDevSoundQueueItem queueItem;
err = iMsgQueue.Receive(queueItem);
if(queueItem.iRequest == EMMFDevSoundProxyMarkEvent)
{
break;
}
// Look for the specific event
else if(queueItem.iRequest != aRequest)
{
// assumes sufficient space in the queue
err = iMsgQueue.Send(queueItem);
}
}
}
SYMBIAN_DEBPRN0(_L("CMMFDevSoundSession[0x%x]::FilterQueueEvent - Exit"));
}
//
// CMMFDevSoundSession::Disconnect
// (other items were commented in a header).
//
void CMMFDevSoundSession::Disconnect(const RMessage2& aMessage)
{
SYMBIAN_DEBPRN0(_L("CMMFDevSoundSession[0x%x]::Disconnect - Enter"));
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"));
}
//
// CMMFDevSoundSession::NewL
// (other items were commented in a header).
//
CMMFDevSoundSession* CMMFDevSoundSession::NewL(MGlobalProperties& aGlobalProperties)
{
CMMFDevSoundSession* self = new (ELeave) CMMFDevSoundSession;
CleanupStack::PushL(self);
self->ConstructL(aGlobalProperties);
CleanupStack::Pop(self);
return self;
}
//
// CMMFDevSoundSession::ConstructL
// (other items were commented in a header).
//
void CMMFDevSoundSession::ConstructL(MGlobalProperties& aGlobalProperties)
{
iAdapter = CMMFDevSoundAdaptation::NewL(*this, aGlobalProperties);
iClosingWait = new(ELeave) CActiveSchedulerWait();
// Create the Custom Interface DeMux Utility
iDeMuxUtility = CMMFDevSoundCIDeMuxUtility::NewL(this);
// Create the Custom Interface extension
TUid implUid = {KMmfUidCIServerExtensionImpl};
TInt uidAsInteger = implUid.iUid;
const TInt KCIExtTempBufferSize = 20;
TBuf8<KCIExtTempBufferSize> tempBuffer;
tempBuffer.Num(uidAsInteger, EHex);
TUid interfaceUid = {KUidDevSoundCIServerExtension};
TUid destructorKey;
TRAPD(err, iCIExtension = static_cast<MDevSoundCIServerExtension*>
(MmPluginUtils::CreateImplementationL(interfaceUid, destructorKey, tempBuffer, KRomOnlyResolverUid)));
if (KErrNotSupported == err)
{
iCIExtension = NULL;
}
else
{
User::LeaveIfError(err);
}
if (iCIExtension)
{
// Extension exists. Complete the setup
iCIExtension->PassDestructorKey(destructorKey);
User::LeaveIfError(iCIExtension->Setup(*this));
}
iQueuedRequests.ReserveL(KMaxQueueRequest);
iAsyncQueueStart = new (ELeave) CAsyncCallBack(CActive::EPriorityStandard);
TCallBack asyncCallback(AsyncQueueStartCallback, this);
iAsyncQueueStart->Set(asyncCallback);
}
// CMMFDevSoundSession::InitializeComplete
// (other items were commented in a header).
//
void CMMFDevSoundSession::InitializeComplete(TInt aError)
{
// this may be a re-initialization and so we need to
// re-get our custom interfaces on the DeMux plugins
TInt count = iCustomInterfaceArray.Count();
for (TInt i = 0; i < count; i++)
{
// we could have already deleted interfaces without
// removing them from the array so check for this
// and only refresh plugin if non-null
MMMFDevSoundCustomInterfaceDeMuxPlugin* ptr = iCustomInterfaceArray[i].iInterface;
if (ptr)
{
// we can't keep track of..
// 1. where a custom interface is implemented
// 2. the uid of the custom interface to be refreshed
// so assume all have to be refreshed
TRAPD(err, ptr->RefreshL());
// Error indicates this is no longer a valid interface
if (err != KErrNone)
{
TMMFEvent event;
TMMFDevSoundQueueItem item;
item.iRequest = EMMFDevSoundCustomCommandCloseMuxDemuxPair;
item.iErrorCode = err;
event.iEventType.iUid = i+1;
item.iEventPckg() = event;
TInt lErr = iMsgQueue.Send(item);
__ASSERT_DEBUG(lErr == KErrNone, Panic(EMsgQueueFailedToSendMsg));
// NB proper panic code required here for this part.
}
}
}
TMMFDevSoundQueueItem item;
item.iRequest = EMMFDevSoundProxyICEvent;
item.iErrorCode = aError;
// assumes sufficient space in the queue so ignores the return value
iMsgQueue.Send(item);
}
//
// CMMFDevSoundSession::ToneFinished
// (other items were commented in a header).
//
void CMMFDevSoundSession::ToneFinished(TInt aError)
{
SYMBIAN_DEBPRN1(_L("CMMFDevSoundSession[0x%x]::ToneFinished - Enter. Error [%d]"), aError);
TMMFDevSoundQueueItem item;
item.iRequest = EMMFDevSoundProxyTFEvent;
item.iErrorCode = aError;
// assumes sufficient space in the queue so ignores the return value
iMsgQueue.Send(item);
SYMBIAN_DEBPRN0(_L("CMMFDevSoundSession[0x%x]::ToneFinished - Exit"));
}
//
// CMMFDevSoundSession::BufferToBeFilled
// (other items were commented in a header).
//
void CMMFDevSoundSession::BufferToBeFilled(CMMFBuffer* aBuffer)
{
SYMBIAN_DEBPRN0(_L("CMMFDevSoundSession[0x%x]::BufferToBeFilled - Enter"));
// Set play error flag to false
iPlayErrorOccured = EFalse;
// Store pointer to the buffer to use it later with PlayData
iBufferPlay = reinterpret_cast<CMMFDataBuffer*>(aBuffer);
TInt status = CreateChunk(iHwBufPckgFill, iBufferPlay->RequestSize());
iHwBufPckgFill().iRequestSize = iBufferPlay->RequestSize();
iHwBufPckgFill().iBufferSize = iBufferPlay->Data().MaxLength();
iHwBufPckgFill().iLastBuffer = iBufferPlay->LastBuffer();
TMMFDevSoundQueueItem queueItem;
if ( status != KErrNone )
{
BufferErrorEvent();
PlayError(status);
}
else
{
queueItem.iRequest = EMMFDevSoundProxyBTBFEvent;
// assumes sufficient space in the queue so ignores the return value
status = iMsgQueue.Send(queueItem);
}
SYMBIAN_DEBPRN1(_L("CMMFDevSoundSession[0x%x]::BufferToBeFilled - Exit [%d]"), status);
}
//
// CMMFDevSoundSession::PlayError
// (other items were commented in a header).
//
void CMMFDevSoundSession::PlayError(TInt aError)
{
SYMBIAN_DEBPRN1(_L("CMMFDevSoundSession[0x%x]::PlayError - Enter [%d]"), aError);
// Set play error flag to ignore following PlayData requests
iPlayErrorOccured = ETrue;
TMMFDevSoundQueueItem item;
item.iRequest = EMMFDevSoundProxyPEEvent;
item.iErrorCode = aError;
iChunk.Close();
// assumes sufficient space in the queue so ignores the return value
iMsgQueue.Send(item);
SYMBIAN_DEBPRN0(_L("CMMFDevSoundSession[0x%x]::PlayError - Exit"));
}
//
// CMMFDevSoundSession::BufferToBeEmptied
// (other items were commented in a header).
//
void CMMFDevSoundSession::BufferToBeEmptied(CMMFBuffer* aBuffer)
{
// Store pointer to the buffer to use it later with RecordData
iBufferRecord = reinterpret_cast<CMMFDataBuffer*>(aBuffer);
TInt status = CreateChunk(iHwBufPckgEmpty, iBufferRecord->RequestSize());
if ( status != KErrNone )
{
BufferErrorEvent();
RecordError(status);
}
else
{
iHwBufPckgEmpty().iRequestSize = iBufferRecord->RequestSize();
iHwBufPckgEmpty().iBufferSize = iBufferRecord->Data().MaxLength();
iHwBufPckgEmpty().iLastBuffer = iBufferRecord->LastBuffer();
//copy the data into the chunk
Mem::Copy(iChunk.Base(),iBufferRecord->Data().Ptr(),iBufferRecord->RequestSize());
TMMFDevSoundQueueItem queueItem;
queueItem.iRequest = EMMFDevSoundProxyBTBEEvent;
// assumes sufficient space in the queue so ignores the return value
iMsgQueue.Send(queueItem);
}
}
// CMMFDevSoundSession::RecordError
// (other items were commented in a header).
//
void CMMFDevSoundSession::RecordError(TInt aError)
{
SYMBIAN_DEBPRN1(_L("CMMFDevSoundSession[0x%x]::Record Error [%d]"), aError);
TMMFDevSoundQueueItem item;
item.iRequest = EMMFDevSoundProxyREEvent;
item.iErrorCode = aError;
iChunk.Close();
// assumes sufficient space in the queue so ignores the return value
iMsgQueue.Send(item);
}
//
// CMMFDevSoundSession::DeviceMessage
// (other items were commented in a header).
//
void CMMFDevSoundSession::DeviceMessage(TUid /*aMessageType*/,
const TDesC8& /*aMsg*/)
{
// Not used
}
void CMMFDevSoundSession::InterfaceDeleted(TUid aInterfaceId)
{
MMMFDevSoundCustomInterfaceDeMuxPlugin* ptr = InterfaceFromUid(aInterfaceId);
if (ptr == NULL)
{
// Not found
return;
}
TRAPD(err, ptr->RefreshL());
if (err != KErrNone)
{
// Refresh failed, so tear down Mux/DeMux pair
TMMFEvent event;
TMMFDevSoundQueueItem item;
item.iRequest = EMMFDevSoundCustomCommandCloseMuxDemuxPair;
item.iErrorCode = err;
event.iEventType = aInterfaceId;
item.iEventPckg() = event;
iMsgQueue.Send(item);
}
}
//
// CMMFDevSoundSession::CallbackFromAdaptorReceived
// (other items were commented in a header).
//
void CMMFDevSoundSession::CallbackFromAdaptorReceived(TInt aType, TInt aError)
{
SYMBIAN_DEBPRN2(_L("CMMFDevSoundSession[0x%x]::CallbackFromAdaptorReceived - Enter. Type[%d] Error[%d]"), aType, aError);
if(aType == KCallbackRecordPauseComplete)
{
TMMFDevSoundQueueItem item;
item.iRequest = EMMFDevSoundProxyPausedRecordCompleteEvent;
item.iErrorCode = KErrNone;
TInt status = iMsgQueue.Send(item);
}
else if(aType == KCallbackAutoPauseResume)
{
TMMFEvent event;
event.iErrorCode = KErrNone;
event.iEventType = KMMFEventCategoryAudioResourceAvailable;
SendEventToClient(event);
//coverity[uninit_use_in_call]
// Disabled Coverity warning, since it complains about iReserved1 member in TMMFEvent being uninitialised
}
else if (aType == KCallbackFlushComplete)
{
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( NeedToQueue() )
{
// If not possible to service now, then queue request
// Encapsule the request
TMMFDevSoundRequest request(aType);
// assumes sufficient space in the queue so ignores the return value
iQueuedRequests.Insert(request, 0);
}
else
{
// If there is no oustanding operation service inmediately
if (aType == KCallbackProcessingFinished)
{
DoProcessingFinished();
}
else if(aType == KCallbackProcessingUnitError)
{
DoProcessingError();
}
}
}
SYMBIAN_DEBPRN0(_L("CMMFDevSoundSession[0x%x]::CallbackFromAdaptorReceived - Exit"));
}
//
// CMMFDevSoundSession::PreemptionStartedCallbackReceived
// (other items were commented in a header).
//
void CMMFDevSoundSession::PreemptionStartedCallbackReceived()
{
SYMBIAN_DEBPRN0(_L("CMMFDevSoundSession[0x%x]::PreemptionStartedCallbackReceived - Enter"));
// Solution: Enqueue any request that arrives before preemption is completed
iOperationCompletePending = ETrue;
SYMBIAN_DEBPRN0(_L("CMMFDevSoundSession[0x%x]::PreemptionStartedCallbackReceived - Exit"));
}
//
// CMMFDevSoundSession::PreemptionFinishedCallbackReceived
// (other items were commented in a header).
//
void CMMFDevSoundSession::PreemptionFinishedCallbackReceived(TBool aCanStartNewOperation)
{
SYMBIAN_DEBPRN0(_L("CMMFDevSoundSession[0x%x]::PreemptionFinishedCallbackReceived - Enter"));
if (iHandlingExtdCI)
{
// we are in the middle of handling a CI, so ignore - will handle later when unwinding
SYMBIAN_DEBPRN0(_L("CMMFDevSoundSession[0x%x]::PreemptionFinishedCallbackReceived - Exit. Exiting from if block for CI"));
return;
}
iOperationCompletePending = EFalse;
if ( aCanStartNewOperation && iQueuedRequests.Count() != 0 )
{
DequeueRequest();
}
SYMBIAN_DEBPRN0(_L("CMMFDevSoundSession[0x%x]::PreemptionFinishedCallbackReceived - Exit"));
}
//
// 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()
//
TBool CMMFDevSoundSession::AdaptorControlsContext() const
{
return !iHandlingExtdCI;
}
MMMFDevSoundCustomInterfaceDeMuxPlugin* CMMFDevSoundSession::InterfaceFromUid(TUid aUid)
{
TInt count = iCustomInterfaceArray.Count();
TInt id = aUid.iUid;
MMMFDevSoundCustomInterfaceDeMuxPlugin* interface = NULL;
for (TInt i = 0; i < count; i++)
{
if (id == iCustomInterfaceArray[i].iId.iUid)
{
interface = iCustomInterfaceArray[i].iInterface;
break;
}
}
return interface;
}
//
// CMMFDevSoundSession::SendEventToClient
// (other items were commented in a header).
//
void CMMFDevSoundSession::SendEventToClient(const TMMFEvent& aEvent)
{
SYMBIAN_DEBPRN0(_L("CMMFDevSoundSession[0x%x]::SendEventToClient - Enter"));
TMMFDevSoundQueueItem item;
item.iRequest = EMMFDevSoundProxySETCEvent;
item.iErrorCode = KErrNone;
item.iEventPckg() = aEvent;
// assumes sufficient space in the queue so ignores the return value
TInt err = iMsgQueue.Send(item);
__ASSERT_DEBUG(err == KErrNone, Panic(EMsgQueueFailedToSendMsg));
SYMBIAN_DEBPRN0(_L("CMMFDevSoundSession[0x%x]::SendEventToClient - Exit"));
}
void CMMFDevSoundSession::AsynchronousOperationComplete(TInt aError, TBool aCanStartNewOperation)
{
__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:
{
SYMBIAN_DEBPRN0(_L("CMMFDevSoundSession[0x%x] ==== ClosingDueException ==== "));
iOperationCompletePending = EFalse;
if(iClosingWait->IsStarted())
{
iClosingWait->AsyncStop();
}
return;
}
// Complete the message for asynchronous requests
case TMMFDevSoundRequest::EConfigure_Asynchronous:
case TMMFDevSoundRequest::EAction_Asynchronous:
case TMMFDevSoundRequest::EQuery_Asynchronous:
case TMMFDevSoundRequest::ECustomInterfacesRelated:
{
if(iOperationCompletePending && aCanStartNewOperation)
{
if (iRequestBeingServiced.Function()==EMMFDevSoundProxyStop)
{
// flush the queue - will have removed any stale items added between initial call and MMRC's reaction
iQueuedRequests.Reset();
FlushEventQueue();
iChunk.Close();
}
if(iRequestBeingServiced.Function()==EMMFDevSoundProxyCapabilities)
{
TMMFDevSoundProxySettings devSoundSet;
devSoundSet.iCaps = iDevSoundCapabilities;
TMMFDevSoundProxySettingsPckg pckg(devSoundSet);
iRequestBeingServiced.Message().Write(TInt(2),pckg);
}
if(iRequestBeingServiced.Function()==EMMFDevSoundProxyCancelInitialize)
{
FlushEventQueue();
}
iRequestBeingServiced.Complete(error);
iOperationCompletePending = EFalse;
}
}
break;
case TMMFDevSoundRequest::EAction_PseudoAsynchronous:
{
if(iOperationCompletePending && aCanStartNewOperation)
{
iOperationCompletePending = EFalse;
}
}
break;
case TMMFDevSoundRequest::EQuery_Synchronous:
case TMMFDevSoundRequest::EConfigure_Synchronous:
case TMMFDevSoundRequest::EBufferExchangeRelated:
break;
case TMMFDevSoundRequest::ECallBackType:
{
if(iOperationCompletePending && aCanStartNewOperation)
{
iOperationCompletePending = EFalse;
}
}
break;
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() );
}
if ( aCanStartNewOperation && iQueuedRequests.Count() != 0 )
{
DequeueRequest();
}
}
void CMMFDevSoundSession::DequeueRequest()
{
SYMBIAN_DEBPRN0(_L("CMMFDevSoundSession[0x%x]::DequeueRequest - Enter"));
iAsyncQueueStart->Cancel(); // if we're in here cancel any background request
TMMFDevSoundRequest msg = iQueuedRequests[0];
if (msg.IsCallBack() > 0)
{
iRequestBeingServiced.SetMessageCallback();
//Call iPf function
SYMBIAN_DEBPRN0(_L("\n CMMFDevSoundSession[0x%x] ======== Service a queued request\n"));
if (msg.IsCallBack() == KCallbackProcessingFinished)
{
iQueuedRequests.Remove(0);
DoProcessingFinished();
}
else if(msg.IsCallBack() == KCallbackProcessingUnitError)
{
iQueuedRequests.Remove(0);
DoProcessingError();
}
}
if (iQueuedRequests.Count()>0)
{
// Some rules about what request can be followed
SYMBIAN_DEBPRN0(_L("\n CMMFDevSoundSession[0x%x]======== Flag can service new request\n"));
iAsyncQueueStart->CallBack();
}
SYMBIAN_DEBPRN0(_L("CMMFDevSoundSession[0x%x]::DequeueRequest - Exit"));
}
// AsyncQueueStartCallback
TInt CMMFDevSoundSession::AsyncQueueStartCallback(TAny* aPtr)
{
CMMFDevSoundSession* self = static_cast<CMMFDevSoundSession*>(aPtr);
self->AsyncQueueStartCallback();
return KErrNone;
}
void CMMFDevSoundSession::AsyncQueueStartCallback()
{
SYMBIAN_DEBPRN0(_L("\n CMMFDevSoundSession[0x%x]======== Service a queued request\n"));
TMMFDevSoundRequest msg = iQueuedRequests[0];
iQueuedRequests.Remove(0);
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
DequeueRequest();
}
}
// CMMFDevSoundSession::CustomInterface()
// Returns a pointer reference to custom interface implementation returned by
// adaptation::CustomInterface method.
// Note this method is called indirectly by CI server-side plugins - both DeMux and
// CIServerExtension call this variously via MMMFDevSoundCustomInterfaceTarget or MCustomInterface
//
TAny* CMMFDevSoundSession::CustomInterface(TUid aInterfaceId)
{
TInt err = DoSetClientConfig(); // if required, this will connect to MMRC etc
if (err)
{
return NULL; // on any error, return NULL - not much more we can do
}
return iAdapter->CustomInterface(aInterfaceId);
}
//
// CMMFDevSoundSession::DoProcessingFinished()
//
void CMMFDevSoundSession::DoProcessingFinished()
{
ResetNotifiedError();
TBool asyncOperation = EFalse;
//ProcessingFinished should never fail
__ASSERT_ALWAYS(KErrNone, iAdapter->ProcessingFinishedReceived(asyncOperation));
iOperationCompletePending = asyncOperation;
if (iOperationCompletePending)
{
iRequestBeingServiced.SetMessageCallback();
}
}
//
// CMMFDevSoundSession::DoProcessingError()
//
void CMMFDevSoundSession::DoProcessingError()
{
ResetNotifiedError();
TBool asyncOperation = EFalse;
//ProcessingFinished should never fail
__ASSERT_ALWAYS(KErrNone, iAdapter->ProcessingError(asyncOperation));
iOperationCompletePending = asyncOperation;
if (iOperationCompletePending)
{
iRequestBeingServiced.SetMessageCallback();
}
}
//
// CMMFDevSoundSession::DoSetClientConfigL()
// Sets client configuration information to Adaptation.
//
TInt CMMFDevSoundSession::DoSetClientConfig()
{
TInt err = KErrNone;
if(!iSetClientConfigApplied)
{
CMMFDevSoundServer* server =
const_cast<CMMFDevSoundServer*>(
static_cast<const CMMFDevSoundServer*>(Server()));
ASSERT(server); // session should always have a server!
TMMFClientConfig clientConfig;
clientConfig.iProcessId = server->ActualProcessId();
err = iAdapter->SetClientConfig(clientConfig);
if (!err)
{
iSetClientConfigApplied = ETrue;
}
}
return err;
}
// CMMFDevSoundSession::DoSetClientConfigL()
// Sets client configuration information to Adaptation.
//
void CMMFDevSoundSession::DoSetClientConfigL()
{
User::LeaveIfError(DoSetClientConfig());
}
//
// CMMFDevSoundSession::CreateChunk()
// Requests kernel to create global RChunk
//
TInt CMMFDevSoundSession::CreateChunk(TMMFDevSoundProxyHwBufPckg& aBufPckg, TInt aRequestedSize)
{
TInt status(KErrNone);
if ( iChunk.Handle() )
{
// If the DevSound Adaptation component requests a buffer size
// that can fit into current chunk's size, then re-use chunk.
if ( aRequestedSize <= iChunk.Size() )
{
if (iForceSendOfChunkHandle)
{
iForceSendOfChunkHandle = EFalse;
aBufPckg().iChunkOp = EOpen;
}
else
{
aBufPckg().iChunkOp = ENull;
}
return status;
}
// The new request size exceeds the current chunk's area, close it. We
// will be creating new one in the following sequences. Note we could
// try to Adjust() the chunk, and see if the existing chunk could be
// extended instead, but this is assumed too rare an event for this
// optimisation
else
{
iChunk.Close();
}
}
// Request kernel to create global RChunk if needed
if ( !iChunk.Handle() )
{
status = iChunk.CreateGlobal(KNullDesC, aRequestedSize, aRequestedSize, EOwnerThread);
if ( status == KErrNone )
{
aBufPckg().iChunkOp = EOpen;
}
else
{
aBufPckg().iChunkOp = ENull;
}
}
iForceSendOfChunkHandle = EFalse;
return status;
}
// Custom Interface //
TInt CMMFDevSoundSession::DoOpenSlaveL(TUid aInterface, const TDesC8& aPackageBuf)
{
// it shouldn't be necessary to check if we have already instantiated this
// interface since the client would already know - however this is something
// that a licensee could implement if they required additional functionality
// e.g. many : 1 mappings between client and DevSound.
MMMFDevSoundCustomInterfaceDeMuxPlugin* ptr = NULL;
// try and instantiate a plugin tunnelling
// pair to support this Custom Interface
ptr = iDeMuxUtility->CreateCustomInterfaceDeMuxL(aInterface);
TInt handle = KNullHandle;
if (ptr)
{
TMMFDevSoundCustomInterfaceDeMuxData data;
data.iInterface = ptr;
data.iId = aInterface;
CleanupReleasePushL(*ptr);
// setup demux plugin
ptr->SetInterfaceTarget(this);
// try and open interface
// this will fetch the interface from the svr implementation
ptr->DoOpenSlaveL(aInterface, aPackageBuf);
User::LeaveIfError(iCustomInterfaceArray.Append(data));
CleanupStack::Pop(); // ptr
handle = iCustomInterfaceArray.Count();
return handle;
}
// we couldn't set up the interface correctly so return a NULL
// handle to the client
return KNullHandle;
}
void CMMFDevSoundSession::DoCloseSlaveL(TInt aHandle)
{
if (aHandle==KNullHandle)
{
// null-handle -> NOP
return;
}
if (aHandle<KNullHandle || aHandle > iCustomInterfaceArray.Count())
{
// handle out of range - should not happen, but leave to show error
User::Leave(KErrBadHandle);
}
TMMFDevSoundCustomInterfaceDeMuxData& data = iCustomInterfaceArray[aHandle-1];
// close and delete the plugin
MMMFDevSoundCustomInterfaceDeMuxPlugin* ptr = data.iInterface;
ptr->DoCloseSlaveL(aHandle);
ptr->Release();
// clear the entry
data.iInterface = NULL;
data.iId.iUid = 0;
}
TInt CMMFDevSoundSession::DoSendSlaveSyncCommandL(const RMmfIpcMessage& aMessage)
{
// use the demux utility to get the handle
TMMFDevSoundCIMessageData data;
iDeMuxUtility->GetSyncMessageDataL(aMessage, data);
TInt handle = data.iHandle;
if ((handle <= 0) || (handle > (iCustomInterfaceArray.Count())))
{
User::Leave(KErrBadHandle);
}
// call on demux plugin
return iCustomInterfaceArray[handle-1].iInterface->DoSendSlaveSyncCommandL(aMessage);
}
TInt CMMFDevSoundSession::DoSendSlaveSyncCommandResultL(const RMmfIpcMessage& aMessage)
{
// use the demux utility to get the handle
TMMFDevSoundCIMessageData data;
iDeMuxUtility->GetSyncMessageDataL(aMessage, data);
TInt handle = data.iHandle;
if ((handle <= 0) || (handle > (iCustomInterfaceArray.Count())))
{
User::Leave(KErrBadHandle);
}
// call on demux plugin
return iCustomInterfaceArray[handle-1].iInterface->DoSendSlaveSyncCommandResultL(aMessage);
}
void CMMFDevSoundSession::DoSendSlaveAsyncCommandL(const RMmfIpcMessage& aMessage)
{
// use the demux utility to get the handle
TMMFDevSoundCIMessageData data;
iDeMuxUtility->GetAsyncMessageDataL(aMessage, data);
TInt handle = data.iHandle;
if ((handle <= 0) || (handle > (iCustomInterfaceArray.Count())))
{
User::Leave(KErrBadHandle);
}
// call on demux plugin
iCustomInterfaceArray[handle-1].iInterface->DoSendSlaveAsyncCommandL(aMessage);
}
void CMMFDevSoundSession::DoSendSlaveAsyncCommandResultL(const RMmfIpcMessage& aMessage)
{
// use the demux utility to get the handle
TMMFDevSoundCIMessageData data;
iDeMuxUtility->GetAsyncMessageDataL(aMessage, data);
TInt handle = data.iHandle;
if ((handle <= 0) || (handle > (iCustomInterfaceArray.Count())))
{
User::Leave(KErrBadHandle);
}
// call on demux plugin
iCustomInterfaceArray[handle-1].iInterface->DoSendSlaveAsyncCommandResultL(aMessage);
}
TBool CMMFDevSoundSession::DoRegisterAsClientL(const RMmfIpcMessage& aMessage)
{
TMMFDevSoundProxySettingsPckg buf;
aMessage.ReadL(0,buf);
HBufC8* notificationRegistrationData = NULL;
notificationRegistrationData = HBufC8::NewLC(User::LeaveIfError(aMessage.GetDesLengthL(1)));
TPtr8 dataPtr(notificationRegistrationData->Des());
aMessage.ReadL(1,dataPtr);
DoSetClientConfigL();// added here instead of the CreateL()
TInt err = KErrNone;
err = iAdapter->RegisterAsClient(buf().iNotificationEventUid,dataPtr);
CleanupStack::PopAndDestroy(1); // Notification Registeration data
if (err != KErrNone)
{
aMessage.Complete(err);
return EFalse;
}
return ETrue;
}
TBool CMMFDevSoundSession::DoCancelRegisterAsClientL(const RMmfIpcMessage& aMessage)
{
TMMFDevSoundProxySettingsPckg buf;
aMessage.ReadL(0,buf);
TInt err = KErrNone;
err = iAdapter->CancelRegisterAsClient(buf().iNotificationEventUid);
if (err != KErrNone)
{
aMessage.Complete(err);
return EFalse;
}
return ETrue;
}
TBool CMMFDevSoundSession::DoGetResourceNotificationDataL(const RMmfIpcMessage& aMessage)
{
TMMFDevSoundProxySettingsPckg buf;
aMessage.ReadL(0,buf);
HBufC8* notificationData = NULL;
notificationData = HBufC8::NewLC(User::LeaveIfError(aMessage.GetDesMaxLengthL(2)));
TPtr8 dataPtr(notificationData->Des());
aMessage.ReadL(2,dataPtr);
TInt err = KErrNone;
err = iAdapter->GetResourceNotificationData(buf().iNotificationEventUid,dataPtr);
aMessage.WriteL(2,*notificationData);
CleanupStack::PopAndDestroy(1); // Notification data
if (err != KErrNone)
{
aMessage.Complete(err);
return EFalse;
}
return ETrue;
}
TBool CMMFDevSoundSession::DoWillResumePlayL(const RMmfIpcMessage& aMessage)
{
TInt err = KErrNone;
err = iAdapter->WillResumePlay();
if (err != KErrNone)
{
aMessage.Complete(err);
return EFalse;
}
return ETrue;
}
TBool CMMFDevSoundSession::DoSetClientThreadInfoL(const RMmfIpcMessage& aMessage)
{
if(!iSetClientConfigApplied)
{
if (aMessage.HasCapability(ECapabilityMultimediaDD) && aMessage.HasCapability(ECapabilityUserEnvironment))
{
TPckgBuf<TThreadId> threadId;
aMessage.ReadL(1, threadId);
CMMFDevSoundServer* server =
const_cast<CMMFDevSoundServer*>(static_cast<const CMMFDevSoundServer*>(Server()));
server->SetClientProcessIdL(threadId());
}
else
{
User::Leave(KErrPermissionDenied);
}
}
else
{
User::Leave(KErrNotReady);
}
return ETrue;
}
void CMMFDevSoundSession::Panic(TMMFDevSoundSessionPanicCodes aCode)
{
User::Panic(KMMFDevSoundSessionPanicCategory, aCode);
}
void CMMFDevSoundSession::BufferErrorEvent()
{
// 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