1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/mm/devsound/a3fdevsound/src/mmfdevsoundproxy/mmfdevsoundcallbackhandler.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,459 @@
1.4 +// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +//
1.18 +
1.19 +
1.20 +
1.21 +// INCLUDE FILES
1.22 +#include "mmfdevsoundproxy.h"
1.23 +#include "mmfdevsoundcallbackhandler.h"
1.24 +#ifdef _DEBUG
1.25 +#include <e32debug.h>
1.26 +
1.27 +#define SYMBIAN_DEBPRN0(str) RDebug::Print(str, this)
1.28 +#define SYMBIAN_DEBPRN1(str, val1) RDebug::Print(str, this, val1)
1.29 +#define SYMBIAN_DEBPRN2(str, val1, val2) RDebug::Print(str, this, val1, val2)
1.30 +#else
1.31 +#define SYMBIAN_DEBPRN0(str)
1.32 +#define SYMBIAN_DEBPRN1(str, val1)
1.33 +#define SYMBIAN_DEBPRN2(str, val1, val2)
1.34 +#endif //_DEBUG
1.35 +
1.36 +// ============================ MEMBER FUNCTIONS ==============================
1.37 +
1.38 +// ----------------------------------------------------------------------------
1.39 +// CMsgQueueHandler::NewL
1.40 +// Two-phased constructor.
1.41 +// ----------------------------------------------------------------------------
1.42 +//
1.43 +CMsgQueueHandler* CMsgQueueHandler::NewL(
1.44 + RMMFDevSoundProxy* aDevSoundProxy,
1.45 + MDevSoundObserver& aDevSoundObserver,
1.46 + RMsgQueue<TMMFDevSoundQueueItem>* aMsgQueue,
1.47 + MMMFDevSoundCustomInterfaceObserver& aDevSoundCIObserver)
1.48 + {
1.49 + CMsgQueueHandler* self = new(ELeave) CMsgQueueHandler(aDevSoundProxy,
1.50 + aDevSoundObserver,
1.51 + aMsgQueue,
1.52 + aDevSoundCIObserver);
1.53 + CleanupStack::PushL(self);
1.54 + self->ConstructL();
1.55 + CleanupStack::Pop(self);
1.56 + return self;
1.57 + }
1.58 +
1.59 +// ----------------------------------------------------------------------------
1.60 +// CMsgQueueHandler::CMsgQueueHandler
1.61 +// C++ default constructor can NOT contain any code, that might leave.
1.62 +// ----------------------------------------------------------------------------
1.63 +//
1.64 +CMsgQueueHandler::CMsgQueueHandler (RMMFDevSoundProxy* aDevSoundProxy,
1.65 + MDevSoundObserver& aDevSoundObserver,
1.66 + RMsgQueue<TMMFDevSoundQueueItem>* aMsgQueue,
1.67 + MMMFDevSoundCustomInterfaceObserver& aDevSoundCIObserver)
1.68 +: CActive(EPriorityStandard),
1.69 + iDevSoundProxy(aDevSoundProxy),
1.70 + iDevSoundObserver(aDevSoundObserver),
1.71 + iMsgQueue(aMsgQueue),
1.72 + iChunkDataPtr(0, 0, 0),
1.73 + iDevSoundCIObserver(aDevSoundCIObserver)
1.74 + {
1.75 + CActiveScheduler::Add(this);
1.76 + }
1.77 +
1.78 +// ----------------------------------------------------------------------------
1.79 +// CMsgQueueHandler::ConstructL
1.80 +// Symbian 2nd phase constructor can leave.
1.81 +// ----------------------------------------------------------------------------
1.82 +//
1.83 +void CMsgQueueHandler::ConstructL()
1.84 + {
1.85 + iEmptyBuffer = CMMFDescriptorBuffer::NewL(0);
1.86 + iAsyncQueueFinish = new (ELeave) CAsyncCallBack(CActive::EPriorityStandard);
1.87 + TCallBack asyncCallback(AsyncQueueFinishCallback, this);
1.88 + iAsyncQueueFinish->Set(asyncCallback);
1.89 + }
1.90 +
1.91 +// ----------------------------------------------------------------------------
1.92 +// CMsgQueueHandler::~CMsgQueueHandler
1.93 +// Destructor.
1.94 +// ----------------------------------------------------------------------------
1.95 +//
1.96 +CMsgQueueHandler::~CMsgQueueHandler()
1.97 + {
1.98 + Cancel();
1.99 + if ( iMsgQueue )
1.100 + {
1.101 + iMsgQueue->Close();
1.102 + }
1.103 + iChunk.Close();
1.104 +
1.105 + delete iDataBuffer;
1.106 + delete iEmptyBuffer;
1.107 + delete iAsyncQueueFinish;
1.108 + }
1.109 +
1.110 +// ----------------------------------------------------------------------------
1.111 +// CMsgQueueHandler::ReceiveEvents
1.112 +// Subscribes for Play Error event from the DevSound server.
1.113 +// ----------------------------------------------------------------------------
1.114 +//
1.115 +void CMsgQueueHandler::ReceiveEvents()
1.116 + {
1.117 + SYMBIAN_DEBPRN0(_L("CMsgQueueHandler[0x%x]::ReceiveEvents - Enter"));
1.118 + if (!IsActive())
1.119 + {
1.120 + iMsgQueue->NotifyDataAvailable(iStatus);
1.121 + SetActive();
1.122 + }
1.123 + SYMBIAN_DEBPRN0(_L("CMsgQueueHandler[0x%x]::ReceiveEvents - Exit"));
1.124 + }
1.125 +
1.126 +// ----------------------------------------------------------------------------
1.127 +// CMsgQueueHandler::RunL
1.128 +// Handles active object’s request completion event.
1.129 +//
1.130 +// ----------------------------------------------------------------------------
1.131 +//
1.132 +void CMsgQueueHandler::RunL()
1.133 + {
1.134 + SYMBIAN_DEBPRN0(_L("CMsgQueueHandler[0x%x]::RunL - Enter"));
1.135 + TInt err = iMsgQueue->Receive(iCurrentItem);
1.136 +
1.137 + if (err == KErrNone || err == KErrUnderflow)
1.138 + {
1.139 + // Signal that we're ready to process the next message
1.140 + ReceiveEvents();
1.141 + }
1.142 +
1.143 + if (err == KErrNone)
1.144 + {
1.145 + switch (iCurrentItem.iRequest)
1.146 + {
1.147 + case EMMFDevSoundProxyICEvent:
1.148 + {
1.149 + DoInitComplete();
1.150 + break;
1.151 + }
1.152 + case EMMFDevSoundProxyBTBFEvent:
1.153 + {
1.154 + iAsyncQueueFinish->Cancel(); // if still active, means previous cycle did not Finish(). Cancel.
1.155 + TRAP(err, DoBTBFCompleteL());
1.156 + if (err)
1.157 + {
1.158 + iAsyncQueueFinish->CallBack(); // async call to Finish()
1.159 + iDevSoundObserver.PlayError(err);
1.160 + }
1.161 + }
1.162 + break;
1.163 + case EMMFDevSoundProxyBTBEEvent:
1.164 + {
1.165 + iAsyncQueueFinish->Cancel(); // if still active, means previous cycle did not Finish(). Cancel.
1.166 + TRAP(err, DoBTBECompleteL());
1.167 + if (err)
1.168 + {
1.169 + iAsyncQueueFinish->CallBack(); // async call to Finish()
1.170 + iDevSoundObserver.RecordError(err);
1.171 + }
1.172 + }
1.173 + break;
1.174 + case EMMFDevSoundProxyPEEvent:
1.175 + {
1.176 + if (iCurrentItem.iErrorCode == KErrDied ||
1.177 + iCurrentItem.iErrorCode == KErrNotReady)
1.178 + {
1.179 + DoPlayErrorComplete();
1.180 + // "this" pointer is no longer valid here as the associated
1.181 + // instance of the DevSound has been deleted along with this
1.182 + // CMsgQueueHandler object. So, we can only return here.
1.183 + return;
1.184 + }
1.185 + else
1.186 + {
1.187 + DoPlayErrorComplete();
1.188 + break;
1.189 + }
1.190 + }
1.191 + case EMMFDevSoundProxyREEvent:
1.192 + {
1.193 + DoRecordErrorComplete();
1.194 + break;
1.195 + }
1.196 + case EMMFDevSoundProxyTFEvent:
1.197 + {
1.198 + DoToneFinishedComplete();
1.199 + break;
1.200 + }
1.201 + case EMMFDevSoundProxySETCEvent:
1.202 + {
1.203 + DoSendEventToClientComplete();
1.204 + break;
1.205 + }
1.206 + case EMMFDevSoundCustomCommandCloseMuxDemuxPair:
1.207 + {
1.208 + TMMFEvent pckgevent = iCurrentItem.iEventPckg();
1.209 + TInt handle = pckgevent.iEventType.iUid;
1.210 + iDevSoundCIObserver.CloseCustomInterface(handle);
1.211 + break;
1.212 + }
1.213 + case EMMFDevSoundProxyPausedRecordCompleteEvent:
1.214 + {
1.215 + DoPausedRecordComplete();
1.216 + break;
1.217 + }
1.218 + default:
1.219 + {
1.220 + break;
1.221 + }
1.222 + }
1.223 + }
1.224 + SYMBIAN_DEBPRN0(_L("CMsgQueueHandler[0x%x]::RunL - Exit"));
1.225 + }
1.226 +
1.227 +// ----------------------------------------------------------------------------
1.228 +// CMsgQueueHandler::RunError
1.229 +// Called by CActive object framework if RunL leaves.
1.230 +// ----------------------------------------------------------------------------
1.231 +//
1.232 +TInt CMsgQueueHandler::RunError(TInt aError)
1.233 + {
1.234 + SYMBIAN_DEBPRN1(_L("CMsgQueueHandler[0x%x]::RunError - Enter. Error [%d]"), aError);
1.235 + TMMFEvent event;
1.236 + event.iErrorCode = aError;
1.237 + iDevSoundObserver.SendEventToClient(event);
1.238 + SYMBIAN_DEBPRN0(_L("CMsgQueueHandler[0x%x]::RunError - Exit"));
1.239 + return KErrNone;
1.240 + }
1.241 +
1.242 +// ----------------------------------------------------------------------------
1.243 +// CMsgQueueHandler::DoCancel
1.244 +// Called when client cancels the wait for a completion of an outstanding
1.245 +// request.
1.246 +// ----------------------------------------------------------------------------
1.247 +//
1.248 +void CMsgQueueHandler::DoCancel()
1.249 + {
1.250 + SYMBIAN_DEBPRN0(_L("CMsgQueueHandler[0x%x]::DoCancel - Enter"));
1.251 + iMsgQueue->CancelDataAvailable();
1.252 + SYMBIAN_DEBPRN0(_L("CMsgQueueHandler[0x%x]::DoCancel - Exit"));
1.253 + }
1.254 +
1.255 +// ----------------------------------------------------------------------------
1.256 +// CMsgQueueHandler::DoInitComplete
1.257 +// Handles initialization completion event.
1.258 +// ----------------------------------------------------------------------------
1.259 +//
1.260 +void CMsgQueueHandler::DoInitComplete()
1.261 + {
1.262 + SYMBIAN_DEBPRN0(_L("CMsgQueueHandler[0x%x]::DoInitComplete - Enter"));
1.263 + iDevSoundObserver.InitializeComplete(iCurrentItem.iErrorCode);
1.264 + SYMBIAN_DEBPRN0(_L("CMsgQueueHandler[0x%x]::DoInitComplete - Exit"));
1.265 + }
1.266 +
1.267 +// ----------------------------------------------------------------------------
1.268 +// CMsgQueueHandler::DoPlayErrorComplete
1.269 +// Handles play completion or cancel event.
1.270 +// ----------------------------------------------------------------------------
1.271 +//
1.272 +void CMsgQueueHandler::DoPlayErrorComplete()
1.273 + {
1.274 + SYMBIAN_DEBPRN0(_L("CMsgQueueHandler[0x%x]::DoPlayErrorComplete - Enter"));
1.275 + iAsyncQueueFinish->CallBack(); // async call to Finish()
1.276 + iDevSoundObserver.PlayError(iCurrentItem.iErrorCode);
1.277 + SYMBIAN_DEBPRN0(_L("CMsgQueueHandler[0x%x]::DoPlayErrorComplete - Exit"));
1.278 + }
1.279 +
1.280 +// ----------------------------------------------------------------------------
1.281 +// CMsgQueueHandler::DoBTBFCompleteL
1.282 +// Handles CMMFDevSound object's data request event to supply CMMFDevSound
1.283 +// with the buffer that it needs to play.
1.284 +// ----------------------------------------------------------------------------
1.285 +//
1.286 +void CMsgQueueHandler::DoBTBFCompleteL()
1.287 + {
1.288 + SYMBIAN_DEBPRN0(_L("CMsgQueueHandler[0x%x]::DoBTBFCompleteL - Enter"));
1.289 + // Returns either chunk handle or NULL
1.290 + // any error is assumed to be due to a pending PlayError(), so the error here is ignored - the PlayError() call will ensure the client remains lively
1.291 + // the chunk has been closed by the server. No action should be taken.
1.292 + TBool requestChunk = iDataBuffer==NULL; // if we have no buffer, tell server we need a chunk handle
1.293 + TInt handle = iDevSoundProxy->BufferToBeFilledData(requestChunk, iSetPckg);
1.294 + if(handle >= KErrNone)
1.295 + {
1.296 + if ( iSetPckg().iChunkOp == EOpen )
1.297 + {
1.298 + AssignDataBufferToChunkL(handle);
1.299 + }
1.300 + else
1.301 + {
1.302 + UpdateDataBufferL();
1.303 + }
1.304 + iDataBuffer->SetStatus(EAvailable);
1.305 +
1.306 + // Let the MMF fill the buffer with data
1.307 +
1.308 + iDevSoundObserver.BufferToBeFilled(iDataBuffer);
1.309 + }
1.310 + SYMBIAN_DEBPRN0(_L("CMsgQueueHandler[0x%x]::DoBTBFCompleteL - Exit"));
1.311 + }
1.312 +
1.313 +// ----------------------------------------------------------------------------
1.314 +// CMsgQueueHandler::DoBTBECompleteL
1.315 +// Handles CMMFDevSound object's data request event to supply CMMFDevSound
1.316 +// with the buffer that it needs to record.
1.317 +// ----------------------------------------------------------------------------
1.318 +//
1.319 +void CMsgQueueHandler::DoBTBECompleteL()
1.320 + {
1.321 + SYMBIAN_DEBPRN0(_L("CMsgQueueHandler[0x%x]::DoBTBECompleteL - Enter"));
1.322 + // Returns either chunk handle or NULL
1.323 + // any error is assumed to be due to a pending RecordError(), so the error here is ignored - the RecordError() call will ensure the client remains lively
1.324 + // the chunk has been closed by the server. No action should be taken.
1.325 + TInt handle = iDevSoundProxy->BufferToBeEmptiedData(iSetPckg);
1.326 + if(handle >= KErrNone)
1.327 + {
1.328 + if ( iSetPckg().iChunkOp == EOpen )
1.329 + {
1.330 + AssignDataBufferToChunkL(handle);
1.331 + }
1.332 + iDataBuffer->SetStatus(EFull);
1.333 + iDataBuffer->Data().SetLength(iSetPckg().iRequestSize);
1.334 + iDevSoundObserver.BufferToBeEmptied(iDataBuffer);
1.335 + }
1.336 + SYMBIAN_DEBPRN0(_L("CMsgQueueHandler[0x%x]::DoBTBECompleteL - Exit"));
1.337 + }
1.338 +
1.339 +// ----------------------------------------------------------------------------
1.340 +// CMsgQueueHandler::DoRecordErrorComplete
1.341 +// Handles record completion or cancel event.
1.342 +// ----------------------------------------------------------------------------
1.343 +//
1.344 +void CMsgQueueHandler::DoRecordErrorComplete()
1.345 + {
1.346 + SYMBIAN_DEBPRN0(_L("CMsgQueueHandler[0x%x]::DoRecordErrorComplete - Enter"));
1.347 + iAsyncQueueFinish->CallBack(); // async call to Finish()
1.348 + iDevSoundObserver.RecordError(iCurrentItem.iErrorCode);
1.349 + SYMBIAN_DEBPRN0(_L("CMsgQueueHandler[0x%x]::DoRecordErrorComplete - Exit"));
1.350 + }
1.351 +
1.352 +// ----------------------------------------------------------------------------
1.353 +// CMsgQueueHandler::DoToneFinishedComplete
1.354 +// Handles tone play completion event.
1.355 +// ----------------------------------------------------------------------------
1.356 +//
1.357 +void CMsgQueueHandler::DoToneFinishedComplete()
1.358 + {
1.359 + SYMBIAN_DEBPRN0(_L("CMsgQueueHandler[0x%x]::DoToneFinishedComplete - Enter"));
1.360 + iDevSoundObserver.ToneFinished(iCurrentItem.iErrorCode);
1.361 + SYMBIAN_DEBPRN0(_L("CMsgQueueHandler[0x%x]::DoToneFinishedComplete - Exit"));
1.362 + }
1.363 +
1.364 +// ----------------------------------------------------------------------------
1.365 +// CMsgQueueHandler::DoSendEventToClientComplete
1.366 +// Sends DevSound server event completion notification to the client.
1.367 +// ----------------------------------------------------------------------------
1.368 +//
1.369 +void CMsgQueueHandler::DoSendEventToClientComplete()
1.370 + {
1.371 + SYMBIAN_DEBPRN0(_L("CMsgQueueHandler[0x%x]::DoSendEventToClientComplete - Enter"));
1.372 + iDevSoundObserver.SendEventToClient(iCurrentItem.iEventPckg());
1.373 + SYMBIAN_DEBPRN0(_L("CMsgQueueHandler[0x%x]::DoSendEventToClientComplete - Exit"));
1.374 + }
1.375 +
1.376 +// ----------------------------------------------------------------------------
1.377 +// CMsgQueueHandler::DoPausedRecordComplete
1.378 +// Handles CMMFDevSound object's data request event to supply CMMFDevSound
1.379 +// with the last buffer that it needs to record.
1.380 +// ----------------------------------------------------------------------------
1.381 +//
1.382 +void CMsgQueueHandler::DoPausedRecordComplete()
1.383 + {
1.384 + SYMBIAN_DEBPRN0(_L("CMsgQueueHandler[0x%x]::DoPausedRecordComplete - Enter"));
1.385 + ASSERT(iEmptyBuffer);
1.386 + iEmptyBuffer->SetLastBuffer(ETrue);
1.387 + iDevSoundObserver.BufferToBeEmptied(iEmptyBuffer);
1.388 + SYMBIAN_DEBPRN0(_L("CMsgQueueHandler[0x%x]::DoPausedRecordComplete - Exit"));
1.389 + }
1.390 +
1.391 +// ----------------------------------------------------------------------------
1.392 +// CMsgQueueHandler::AssignDataBufferToChunkL
1.393 +// Updates chunk handle.
1.394 +// ----------------------------------------------------------------------------
1.395 +//
1.396 +void CMsgQueueHandler::AssignDataBufferToChunkL(TInt aHandle)
1.397 + {
1.398 + SYMBIAN_DEBPRN0(_L("CMsgQueueHandler[0x%x]::AssignDataBufferToChunkL - Enter"));
1.399 + if ( iChunk.Handle() )
1.400 + {
1.401 + iChunk.Close();
1.402 + }
1.403 + User::LeaveIfError(iChunk.SetReturnedHandle(aHandle));
1.404 + // Adjust ptr to map only requested size
1.405 + // The existing clients should handle TPtr with length zero and max length
1.406 + // iSetPckg().iBufferSize.
1.407 + // When we make sure every client handles it, replace second parameter with
1.408 + // zero.
1.409 + //iChunkDataPtr.Set(iChunk.Base(), 0, iSetPckg().iBufferSize);
1.410 + iChunkDataPtr.Set(iChunk.Base(), iSetPckg().iBufferSize, iSetPckg().iBufferSize);
1.411 + if (!iDataBuffer)
1.412 + {
1.413 + iDataBuffer = CMMFPtrBuffer::NewL();
1.414 + }
1.415 + UpdateDataBufferL();
1.416 + SYMBIAN_DEBPRN0(_L("CMsgQueueHandler[0x%x]::AssignDataBufferToChunkL - Exit"));
1.417 + }
1.418 +
1.419 +void CMsgQueueHandler::UpdateDataBufferL()
1.420 + {
1.421 + SYMBIAN_DEBPRN0(_L("CMsgQueueHandler[0x%x]::UpdateDataBufferL - Enter"));
1.422 + ASSERT(iDataBuffer); // to get here, we should have a data buffer
1.423 + iDataBuffer->SetPtr(iChunkDataPtr);
1.424 + iDataBuffer->SetRequestSizeL(iSetPckg().iRequestSize);
1.425 + iDataBuffer->SetLastBuffer(EFalse);
1.426 + SYMBIAN_DEBPRN0(_L("CMsgQueueHandler[0x%x]::UpdateDataBufferL - Exit"));
1.427 + }
1.428 +
1.429 +void CMsgQueueHandler::Finish()
1.430 + {
1.431 + SYMBIAN_DEBPRN0(_L("CMsgQueueHandler[0x%x]::Finish - Enter"));
1.432 + if (iDataBuffer)
1.433 + {
1.434 + delete iDataBuffer;
1.435 + iDataBuffer = NULL;
1.436 + }
1.437 + if (iChunk.Handle())
1.438 + {
1.439 + iChunk.Close();
1.440 + }
1.441 + SYMBIAN_DEBPRN0(_L("CMsgQueueHandler[0x%x]::Finish - Exit"));
1.442 + }
1.443 +
1.444 +// AsyncQueueStartCallback
1.445 +
1.446 +
1.447 +TInt CMsgQueueHandler::AsyncQueueFinishCallback(TAny* aPtr)
1.448 + {
1.449 + CMsgQueueHandler* self = static_cast<CMsgQueueHandler*>(aPtr);
1.450 + self->DoAsyncQueueFinishCallback();
1.451 + return KErrNone;
1.452 + }
1.453 +
1.454 +void CMsgQueueHandler::DoAsyncQueueFinishCallback()
1.455 + {
1.456 + SYMBIAN_DEBPRN0(_L("CMsgQueueHandler[0x%x]::DoAsyncQueueFinishCallback - Enter"));
1.457 + Finish();
1.458 + SYMBIAN_DEBPRN0(_L("CMsgQueueHandler[0x%x]::DoAsyncQueueFinishCallback - Exit"));
1.459 + }
1.460 +
1.461 +
1.462 +// End of File