os/mm/devsound/a3fdevsound/src/mmfdevsoundproxy/mmfdevsoundcallbackhandler.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 // Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
     2 // All rights reserved.
     3 // This component and the accompanying materials are made available
     4 // under the terms of "Eclipse Public License v1.0"
     5 // which accompanies this distribution, and is available
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 //
    15 
    16 
    17 
    18 // INCLUDE FILES
    19 #include "mmfdevsoundproxy.h"
    20 #include "mmfdevsoundcallbackhandler.h"
    21 #ifdef _DEBUG
    22 #include <e32debug.h>
    23 
    24 #define SYMBIAN_DEBPRN0(str)                RDebug::Print(str, this)
    25 #define SYMBIAN_DEBPRN1(str, val1)          RDebug::Print(str, this, val1)
    26 #define SYMBIAN_DEBPRN2(str, val1, val2)    RDebug::Print(str, this, val1, val2)
    27 #else
    28 #define SYMBIAN_DEBPRN0(str)
    29 #define SYMBIAN_DEBPRN1(str, val1)
    30 #define SYMBIAN_DEBPRN2(str, val1, val2)
    31 #endif //_DEBUG
    32 
    33 // ============================ MEMBER FUNCTIONS ==============================
    34 
    35 // ----------------------------------------------------------------------------
    36 // CMsgQueueHandler::NewL
    37 // Two-phased constructor.
    38 // ----------------------------------------------------------------------------
    39 //
    40 CMsgQueueHandler* CMsgQueueHandler::NewL(
    41 						RMMFDevSoundProxy* aDevSoundProxy,
    42 						MDevSoundObserver& aDevSoundObserver,
    43 						RMsgQueue<TMMFDevSoundQueueItem>* aMsgQueue,
    44 						MMMFDevSoundCustomInterfaceObserver& aDevSoundCIObserver)
    45 	{
    46 	CMsgQueueHandler* self = new(ELeave) CMsgQueueHandler(aDevSoundProxy,
    47 														aDevSoundObserver,
    48 														aMsgQueue,
    49 														aDevSoundCIObserver);
    50 	CleanupStack::PushL(self);
    51 	self->ConstructL();
    52 	CleanupStack::Pop(self);
    53 	return self;
    54 	}
    55 
    56 // ----------------------------------------------------------------------------
    57 // CMsgQueueHandler::CMsgQueueHandler
    58 // C++ default constructor can NOT contain any code, that might leave.
    59 // ----------------------------------------------------------------------------
    60 //
    61 CMsgQueueHandler::CMsgQueueHandler (RMMFDevSoundProxy* aDevSoundProxy,
    62 									MDevSoundObserver& aDevSoundObserver,
    63 									RMsgQueue<TMMFDevSoundQueueItem>* aMsgQueue,
    64 									MMMFDevSoundCustomInterfaceObserver& aDevSoundCIObserver)
    65 :	CActive(EPriorityStandard),
    66 	iDevSoundProxy(aDevSoundProxy),
    67 	iDevSoundObserver(aDevSoundObserver),
    68 	iMsgQueue(aMsgQueue),
    69 	iChunkDataPtr(0, 0, 0),
    70 	iDevSoundCIObserver(aDevSoundCIObserver)
    71 	{
    72 	CActiveScheduler::Add(this);
    73 	}
    74 
    75 // ----------------------------------------------------------------------------
    76 // CMsgQueueHandler::ConstructL
    77 // Symbian 2nd phase constructor can leave.
    78 // ----------------------------------------------------------------------------
    79 //
    80 void CMsgQueueHandler::ConstructL()
    81 	{
    82 	iEmptyBuffer = CMMFDescriptorBuffer::NewL(0);
    83 	iAsyncQueueFinish = new (ELeave) CAsyncCallBack(CActive::EPriorityStandard);
    84 	TCallBack asyncCallback(AsyncQueueFinishCallback, this);
    85 	iAsyncQueueFinish->Set(asyncCallback);
    86 	}
    87 
    88 // ----------------------------------------------------------------------------
    89 // CMsgQueueHandler::~CMsgQueueHandler
    90 // Destructor.
    91 // ----------------------------------------------------------------------------
    92 //
    93 CMsgQueueHandler::~CMsgQueueHandler()
    94 	{
    95 	Cancel();
    96 	if ( iMsgQueue )
    97 		{
    98 		iMsgQueue->Close();
    99 		}
   100 	iChunk.Close();
   101 	
   102 	delete iDataBuffer;
   103 	delete iEmptyBuffer;
   104 	delete iAsyncQueueFinish;
   105 	}
   106 
   107 // ----------------------------------------------------------------------------
   108 // CMsgQueueHandler::ReceiveEvents
   109 // Subscribes for Play Error event from the DevSound server.
   110 // ----------------------------------------------------------------------------
   111 //
   112 void CMsgQueueHandler::ReceiveEvents()
   113 	{
   114     SYMBIAN_DEBPRN0(_L("CMsgQueueHandler[0x%x]::ReceiveEvents - Enter"));	
   115     if (!IsActive())
   116 		{
   117 		iMsgQueue->NotifyDataAvailable(iStatus);
   118 		SetActive();
   119 		}
   120     SYMBIAN_DEBPRN0(_L("CMsgQueueHandler[0x%x]::ReceiveEvents - Exit"));
   121 	}
   122 
   123 // ----------------------------------------------------------------------------
   124 // CMsgQueueHandler::RunL
   125 // Handles active object’s request completion event.
   126 //
   127 // ----------------------------------------------------------------------------
   128 //
   129 void CMsgQueueHandler::RunL()
   130 	{
   131     SYMBIAN_DEBPRN0(_L("CMsgQueueHandler[0x%x]::RunL - Enter"));
   132     TInt err = iMsgQueue->Receive(iCurrentItem);
   133 
   134 	if (err == KErrNone || err == KErrUnderflow)
   135 		{
   136 		// Signal that we're ready to process the next message
   137 		ReceiveEvents();
   138 		}
   139 
   140 	if (err == KErrNone)
   141 		{
   142 		switch (iCurrentItem.iRequest)
   143 			{
   144 			case EMMFDevSoundProxyICEvent:
   145 				{
   146 				DoInitComplete();
   147 				break;
   148 				}
   149 			case EMMFDevSoundProxyBTBFEvent:
   150 				{
   151 				iAsyncQueueFinish->Cancel(); // if still active, means previous cycle did not Finish(). Cancel.
   152 				TRAP(err, DoBTBFCompleteL());
   153 				if (err)
   154 					{
   155 					iAsyncQueueFinish->CallBack(); // async call to Finish()
   156 					iDevSoundObserver.PlayError(err);
   157 					}
   158 				}
   159 				break;
   160 			case EMMFDevSoundProxyBTBEEvent:
   161 				{
   162 				iAsyncQueueFinish->Cancel(); // if still active, means previous cycle did not Finish(). Cancel.
   163 				TRAP(err, DoBTBECompleteL());
   164 				if (err)
   165 					{
   166 					iAsyncQueueFinish->CallBack(); // async call to Finish()
   167 					iDevSoundObserver.RecordError(err);
   168 					}
   169 				}
   170 				break;
   171 			case EMMFDevSoundProxyPEEvent:
   172 				{
   173 				if (iCurrentItem.iErrorCode == KErrDied ||
   174 					iCurrentItem.iErrorCode == KErrNotReady)
   175 					{ 
   176 					DoPlayErrorComplete();
   177 					// "this" pointer is no longer valid here as the associated
   178 					// instance of the DevSound has been deleted along with this
   179 					// CMsgQueueHandler object. So, we can only return here.
   180 					return;
   181 					}
   182 				else
   183 					{
   184 					DoPlayErrorComplete();
   185 					break;
   186 					}
   187 				}
   188 			case EMMFDevSoundProxyREEvent:
   189 				{
   190 				DoRecordErrorComplete();
   191 				break;
   192 				}
   193 			case EMMFDevSoundProxyTFEvent:
   194 				{
   195 				DoToneFinishedComplete();
   196 				break;
   197 				}
   198 			case EMMFDevSoundProxySETCEvent:
   199 				{
   200 				DoSendEventToClientComplete();
   201 				break;
   202 				}
   203 			case EMMFDevSoundCustomCommandCloseMuxDemuxPair:
   204 				{
   205 				TMMFEvent pckgevent = iCurrentItem.iEventPckg();
   206 				TInt handle = pckgevent.iEventType.iUid;
   207 				iDevSoundCIObserver.CloseCustomInterface(handle);
   208 				break;
   209 				}
   210 			case EMMFDevSoundProxyPausedRecordCompleteEvent:
   211 				{
   212 				DoPausedRecordComplete();
   213 				break;
   214 				}
   215 			default:
   216 				{
   217 				break;
   218 				}
   219 			}
   220 		}
   221 	SYMBIAN_DEBPRN0(_L("CMsgQueueHandler[0x%x]::RunL - Exit"));
   222 	}
   223 
   224 // ----------------------------------------------------------------------------
   225 // CMsgQueueHandler::RunError
   226 // Called by CActive object framework if RunL leaves.
   227 // ----------------------------------------------------------------------------
   228 //
   229 TInt CMsgQueueHandler::RunError(TInt aError)
   230 	{
   231     SYMBIAN_DEBPRN1(_L("CMsgQueueHandler[0x%x]::RunError - Enter. Error [%d]"), aError);
   232     TMMFEvent event;
   233 	event.iErrorCode = aError;
   234 	iDevSoundObserver.SendEventToClient(event);
   235 	SYMBIAN_DEBPRN0(_L("CMsgQueueHandler[0x%x]::RunError - Exit"));
   236 	return KErrNone;
   237 	}
   238 
   239 // ----------------------------------------------------------------------------
   240 // CMsgQueueHandler::DoCancel
   241 // Called when client cancels the wait for a completion of an outstanding
   242 // request.
   243 // ----------------------------------------------------------------------------
   244 //
   245 void CMsgQueueHandler::DoCancel()
   246 	{
   247     SYMBIAN_DEBPRN0(_L("CMsgQueueHandler[0x%x]::DoCancel - Enter"));
   248     iMsgQueue->CancelDataAvailable();
   249     SYMBIAN_DEBPRN0(_L("CMsgQueueHandler[0x%x]::DoCancel - Exit"));
   250 	}
   251 
   252 // ----------------------------------------------------------------------------
   253 // CMsgQueueHandler::DoInitComplete
   254 // Handles initialization completion event.
   255 // ----------------------------------------------------------------------------
   256 //
   257 void CMsgQueueHandler::DoInitComplete()
   258 	{
   259     SYMBIAN_DEBPRN0(_L("CMsgQueueHandler[0x%x]::DoInitComplete - Enter"));
   260     iDevSoundObserver.InitializeComplete(iCurrentItem.iErrorCode);
   261     SYMBIAN_DEBPRN0(_L("CMsgQueueHandler[0x%x]::DoInitComplete - Exit"));
   262 	}
   263 
   264 // ----------------------------------------------------------------------------
   265 // CMsgQueueHandler::DoPlayErrorComplete
   266 // Handles play completion or cancel event.
   267 // ----------------------------------------------------------------------------
   268 //
   269 void CMsgQueueHandler::DoPlayErrorComplete()
   270 	{
   271     SYMBIAN_DEBPRN0(_L("CMsgQueueHandler[0x%x]::DoPlayErrorComplete - Enter"));
   272     iAsyncQueueFinish->CallBack(); // async call to Finish()
   273 	iDevSoundObserver.PlayError(iCurrentItem.iErrorCode);
   274 	SYMBIAN_DEBPRN0(_L("CMsgQueueHandler[0x%x]::DoPlayErrorComplete - Exit"));
   275 	}
   276 
   277 // ----------------------------------------------------------------------------
   278 // CMsgQueueHandler::DoBTBFCompleteL
   279 // Handles CMMFDevSound object's data request event to supply CMMFDevSound
   280 // with the buffer that it needs to play.
   281 // ----------------------------------------------------------------------------
   282 //
   283 void CMsgQueueHandler::DoBTBFCompleteL()
   284 	{
   285     SYMBIAN_DEBPRN0(_L("CMsgQueueHandler[0x%x]::DoBTBFCompleteL - Enter"));
   286     // Returns either chunk handle or NULL
   287 	// 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
   288 	// the chunk has been closed by the server. No action should be taken.
   289 	TBool requestChunk = iDataBuffer==NULL; // if we have no buffer, tell server we need a chunk handle
   290 	TInt handle = iDevSoundProxy->BufferToBeFilledData(requestChunk, iSetPckg);
   291 	if(handle >= KErrNone)
   292 		{
   293 		if ( iSetPckg().iChunkOp == EOpen )
   294 			{
   295 			AssignDataBufferToChunkL(handle);
   296 			}
   297 		else
   298 			{
   299 			UpdateDataBufferL();
   300 			}
   301 		iDataBuffer->SetStatus(EAvailable);
   302 		
   303 		// Let the MMF fill the buffer with data
   304 		
   305 		iDevSoundObserver.BufferToBeFilled(iDataBuffer);
   306 		}
   307 	SYMBIAN_DEBPRN0(_L("CMsgQueueHandler[0x%x]::DoBTBFCompleteL - Exit"));
   308 	}
   309 
   310 // ----------------------------------------------------------------------------
   311 // CMsgQueueHandler::DoBTBECompleteL
   312 // Handles CMMFDevSound object's data request event to supply CMMFDevSound
   313 // with the buffer that it needs to record.
   314 // ----------------------------------------------------------------------------
   315 //
   316 void CMsgQueueHandler::DoBTBECompleteL()
   317 	{
   318     SYMBIAN_DEBPRN0(_L("CMsgQueueHandler[0x%x]::DoBTBECompleteL - Enter"));
   319     // Returns either chunk handle or NULL
   320 	// 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
   321 	// the chunk has been closed by the server. No action should be taken.
   322 	TInt handle = iDevSoundProxy->BufferToBeEmptiedData(iSetPckg);
   323 	if(handle >= KErrNone)
   324 		{
   325 		if ( iSetPckg().iChunkOp == EOpen )
   326 			{
   327 			AssignDataBufferToChunkL(handle);
   328 			}
   329 		iDataBuffer->SetStatus(EFull);	
   330 		iDataBuffer->Data().SetLength(iSetPckg().iRequestSize);
   331 		iDevSoundObserver.BufferToBeEmptied(iDataBuffer);
   332 		}
   333 	SYMBIAN_DEBPRN0(_L("CMsgQueueHandler[0x%x]::DoBTBECompleteL - Exit"));
   334 	}
   335 
   336 // ----------------------------------------------------------------------------
   337 // CMsgQueueHandler::DoRecordErrorComplete
   338 // Handles record completion or cancel event.
   339 // ----------------------------------------------------------------------------
   340 //
   341 void CMsgQueueHandler::DoRecordErrorComplete()
   342 	{
   343     SYMBIAN_DEBPRN0(_L("CMsgQueueHandler[0x%x]::DoRecordErrorComplete - Enter"));
   344     iAsyncQueueFinish->CallBack(); // async call to Finish()
   345 	iDevSoundObserver.RecordError(iCurrentItem.iErrorCode);
   346 	SYMBIAN_DEBPRN0(_L("CMsgQueueHandler[0x%x]::DoRecordErrorComplete - Exit"));
   347 	}
   348 
   349 // ----------------------------------------------------------------------------
   350 // CMsgQueueHandler::DoToneFinishedComplete
   351 // Handles tone play completion event.
   352 // ----------------------------------------------------------------------------
   353 //
   354 void CMsgQueueHandler::DoToneFinishedComplete()
   355 	{
   356     SYMBIAN_DEBPRN0(_L("CMsgQueueHandler[0x%x]::DoToneFinishedComplete - Enter"));
   357     iDevSoundObserver.ToneFinished(iCurrentItem.iErrorCode);
   358     SYMBIAN_DEBPRN0(_L("CMsgQueueHandler[0x%x]::DoToneFinishedComplete - Exit"));
   359 	}
   360 
   361 // ----------------------------------------------------------------------------
   362 // CMsgQueueHandler::DoSendEventToClientComplete
   363 // Sends DevSound server event completion notification to the client.
   364 // ----------------------------------------------------------------------------
   365 //
   366 void CMsgQueueHandler::DoSendEventToClientComplete()
   367 	{
   368     SYMBIAN_DEBPRN0(_L("CMsgQueueHandler[0x%x]::DoSendEventToClientComplete - Enter"));
   369     iDevSoundObserver.SendEventToClient(iCurrentItem.iEventPckg());
   370     SYMBIAN_DEBPRN0(_L("CMsgQueueHandler[0x%x]::DoSendEventToClientComplete - Exit"));
   371 	}
   372 
   373 // ----------------------------------------------------------------------------
   374 // CMsgQueueHandler::DoPausedRecordComplete
   375 // Handles CMMFDevSound object's data request event to supply CMMFDevSound
   376 // with the last buffer that it needs to record.
   377 // ----------------------------------------------------------------------------
   378 //
   379 void CMsgQueueHandler::DoPausedRecordComplete()
   380 	{
   381     SYMBIAN_DEBPRN0(_L("CMsgQueueHandler[0x%x]::DoPausedRecordComplete - Enter"));
   382     ASSERT(iEmptyBuffer);
   383 	iEmptyBuffer->SetLastBuffer(ETrue);
   384 	iDevSoundObserver.BufferToBeEmptied(iEmptyBuffer);
   385 	SYMBIAN_DEBPRN0(_L("CMsgQueueHandler[0x%x]::DoPausedRecordComplete - Exit"));
   386 	}
   387 
   388 // ----------------------------------------------------------------------------
   389 // CMsgQueueHandler::AssignDataBufferToChunkL
   390 // Updates chunk handle.
   391 // ----------------------------------------------------------------------------
   392 //
   393 void CMsgQueueHandler::AssignDataBufferToChunkL(TInt aHandle)
   394 	{
   395     SYMBIAN_DEBPRN0(_L("CMsgQueueHandler[0x%x]::AssignDataBufferToChunkL - Enter"));
   396     if ( iChunk.Handle() )
   397 		{
   398 		iChunk.Close();
   399 		}
   400 	User::LeaveIfError(iChunk.SetReturnedHandle(aHandle));
   401 	// Adjust ptr to map only requested size
   402 	// The existing clients should handle TPtr with length zero and max length
   403 	// iSetPckg().iBufferSize.
   404 	// When we make sure every client handles it, replace second parameter with
   405 	// zero.
   406 	//iChunkDataPtr.Set(iChunk.Base(), 0, iSetPckg().iBufferSize);
   407 	iChunkDataPtr.Set(iChunk.Base(), iSetPckg().iBufferSize, iSetPckg().iBufferSize);
   408 	if (!iDataBuffer)
   409 		{
   410 		iDataBuffer = CMMFPtrBuffer::NewL();	
   411 		}
   412 	UpdateDataBufferL();
   413 	SYMBIAN_DEBPRN0(_L("CMsgQueueHandler[0x%x]::AssignDataBufferToChunkL - Exit"));
   414 	}
   415 	
   416 void CMsgQueueHandler::UpdateDataBufferL()
   417 	{
   418     SYMBIAN_DEBPRN0(_L("CMsgQueueHandler[0x%x]::UpdateDataBufferL - Enter"));
   419     ASSERT(iDataBuffer); // to get here, we should have a data buffer
   420 	iDataBuffer->SetPtr(iChunkDataPtr);
   421 	iDataBuffer->SetRequestSizeL(iSetPckg().iRequestSize);
   422 	iDataBuffer->SetLastBuffer(EFalse);
   423 	SYMBIAN_DEBPRN0(_L("CMsgQueueHandler[0x%x]::UpdateDataBufferL - Exit"));
   424 	}
   425 	
   426 void CMsgQueueHandler::Finish()
   427 	{
   428     SYMBIAN_DEBPRN0(_L("CMsgQueueHandler[0x%x]::Finish - Enter"));
   429     if (iDataBuffer)
   430 		{
   431 		delete iDataBuffer;
   432 		iDataBuffer = NULL;
   433 		}
   434 	if (iChunk.Handle())
   435 		{
   436 		iChunk.Close();
   437 		}
   438 	SYMBIAN_DEBPRN0(_L("CMsgQueueHandler[0x%x]::Finish - Exit"));
   439 	}
   440 
   441 // 	AsyncQueueStartCallback
   442 
   443 
   444 TInt CMsgQueueHandler::AsyncQueueFinishCallback(TAny* aPtr)
   445 	{
   446     CMsgQueueHandler* self = static_cast<CMsgQueueHandler*>(aPtr);
   447 	self->DoAsyncQueueFinishCallback();
   448 	return KErrNone;
   449 	}
   450 	
   451 void CMsgQueueHandler::DoAsyncQueueFinishCallback()
   452 	{
   453     SYMBIAN_DEBPRN0(_L("CMsgQueueHandler[0x%x]::DoAsyncQueueFinishCallback - Enter"));
   454     Finish();
   455     SYMBIAN_DEBPRN0(_L("CMsgQueueHandler[0x%x]::DoAsyncQueueFinishCallback - Exit"));
   456 	}
   457 
   458 
   459 // End of File