os/mm/mmlibs/mmfw/tsrc/mmfintegrationtest/Ctlfrm/TSI_MmfCtlfrmStep.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 // Copyright (c) 2002-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 // TSIMmfCtlfrmStep.cpp
    15 // 
    16 //
    17 
    18 // EPOC includes
    19 #include <e32base.h>
    20 
    21 // Test system includes
    22 #include <testframework.h>
    23 #include "TSI_MmfCtlfrmStep.h"
    24 #include "TSI_MmfCtlfrmSuite.h"
    25 #include "TSI_MmfCodes.h"
    26 #include "TSI_MmfEventIds.h"
    27 #include "ActrlTestUids.h"
    28 
    29 #include <mmf/common/mmfcontroller.h>
    30 #include <mmf/plugin/mmfcontrollerimplementationuids.hrh>
    31 
    32 const TUid KTestControllerUid = {KTSIMmfControllerUid};
    33 const TUid KTestController2Uid = {KTSIMmfController2Uid};
    34 //const TUid KTestDataSourceUid = {KTSIMmfDataSourceUid};	
    35 //const TUid KTestDataSinkUid   = {KTSIMmfDataSinkUid};		
    36 
    37 // audio controller, from mmfControllerImplementationUIDs.hrh
    38 //const TUid KTestAudioControllerUid = {KMmfUidControllerAudio};	
    39 
    40 // event values for audio controller testing
    41 const TInt KDelay            = 1000000;
    42 const TInt KMaxRetries       = 12;
    43 
    44 
    45 // ---------------------------
    46 // RTestStepMmfCtlfrm
    47 // base class
    48 
    49 RTestStepMmfCtlfrm::RTestStepMmfCtlfrm() 
    50 	{
    51 	}
    52 
    53 // ---------------------------
    54 // RTestStepMmfCtlfrmTest1
    55 // base class with preamble / postamble to open and close the test controller
    56 
    57 TVerdict RTestStepMmfCtlfrmTest1::OpenL() 
    58 	{
    59 	TInt error = KErrNone;
    60 
    61 	iSettings.iPriority = ETSIMmfPriorityLow;
    62 	iSettings.iPref = EMdaPriorityPreferenceTime;
    63 	iSettings.iState = EMMFStateIdle;
    64 
    65 	// Open a controller
    66 	error = iController.Open(KTestControllerUid, iSettings);
    67 	if (error)
    68 		{
    69 		ERR_PRINTF2(_L("controller failed to open, error %d"), error);
    70 		return iTestStepResult = EInconclusive;
    71 		}
    72 
    73 	return iTestStepResult = EPass;
    74 	}
    75 
    76 void RTestStepMmfCtlfrmTest1::Close() 
    77 	{
    78 	iController.Close();
    79 
    80 	// close controller delay - ensure it has time to finish
    81 	// (so we don't get access violation from something trying to dequeue it before it's closed)
    82 	const TTimeIntervalMicroSeconds32 KCloseControllerDelay = 500000L;
    83 	User::After(KCloseControllerDelay);
    84 	}
    85 
    86 // ---------------------------
    87 // RTestStepMmfCtlfrmTest2
    88 // base class with preamble / postamble to open and close the test controller 2
    89 
    90 TVerdict RTestStepMmfCtlfrmTest2::OpenL() 
    91 	{
    92 	TInt error = KErrNone;
    93 
    94 	iSettings.iPriority = ETSIMmfPriorityLow;
    95 	iSettings.iPref = EMdaPriorityPreferenceTime;
    96 	iSettings.iState = EMMFStateIdle;
    97 
    98 	// Open a controller
    99 	error = iController.Open(KTestController2Uid, iSettings);
   100 	if (error)
   101 		{
   102 		ERR_PRINTF2(_L("controller failed to open, error %d"), error);
   103 		return iTestStepResult = EInconclusive;
   104 		}
   105 
   106 	return iTestStepResult = EPass;
   107 	}
   108 
   109 void RTestStepMmfCtlfrmTest2::Close() 
   110 	{
   111 	iController.Close();
   112 	// close controller delay - ensure it has time to finish
   113 	// (so we don't get access violation from something trying to dequeue it before it's closed)
   114 	const TTimeIntervalMicroSeconds32 KCloseControllerDelay = 500000L;
   115 	User::After(KCloseControllerDelay);
   116 	}
   117 
   118 // ---------------------------
   119 // RTestStepMmfCtlfrmAudio
   120 // base class with preamble / postamble to open and close the audio controller
   121 
   122 TVerdict RTestStepMmfCtlfrmAudio::OpenL() 
   123 	{
   124 	TInt error = KErrNone;
   125 
   126 	iSettings.iPriority = ETSIMmfPriorityHigh;
   127 	iSettings.iPref = EMdaPriorityPreferenceQuality;
   128 	iSettings.iState = EMMFStateIdle;
   129 
   130 	// Open a controller
   131 	error = iController.Open(KUidCustomTestAudioPlugin, iSettings);
   132 //	error = iController.Open(KTestAudioControllerUid, iSettings);
   133 	if (error)
   134 		{
   135 		ERR_PRINTF2(_L("controller failed to open, error %d"), error);
   136 		return iTestStepResult = EInconclusive;
   137 		}
   138 
   139 	INFO_PRINTF2(_L("Opened Custom Audio Controller, UID 0x%8x"), KUidCustomTestAudioPlugin);
   140 	// Add a source and sink
   141 	_LIT(KTestWavFile, "c:\\TsiMmfCtlfrmData\\test.wav");
   142 	iFileConfig().iPath = KTestWavFile;
   143 	error = iController.AddDataSource(KUidMmfFileSource, iFileConfig);
   144 	if (error)
   145 		{
   146 		ERR_PRINTF2(_L("failed to add a data source, error %d"), error);
   147 		Close();
   148 		return iTestStepResult = EInconclusive;
   149 		}
   150 	error = iController.AddDataSink(KUidMmfAudioOutput, KNullDesC8);
   151 	if (error)
   152 		{
   153 		ERR_PRINTF2(_L("failed to add a data sink, error %d"), error);
   154 		Close();
   155 		return iTestStepResult = EInconclusive;
   156 		}
   157 	
   158 	return iTestStepResult = EPass;
   159 	}
   160 
   161 void RTestStepMmfCtlfrmAudio::Close() 
   162 	{
   163 	iController.Stop();
   164 	iController.Reset();
   165 	iController.Close();
   166 	// close controller delay - ensure it has time to finish
   167 	// (so we don't get access violation from something trying to dequeue it before it's closed)
   168 	const TTimeIntervalMicroSeconds32 KCloseControllerDelay = 500000L;
   169 	User::After(KCloseControllerDelay);
   170 	}
   171 
   172 // Searches for an event
   173 TVerdict RTestStepMmfCtlfrmAudio::SearchForEvent( TMMFEvent& aEvent )
   174 	{
   175 #ifdef EVENT_SEARCH_DISABLED
   176 	WARN_PRINTF1(_L("Warning : SearchForEvent disabled"));
   177     TMMFEvent dummyEvent; // JS
   178 	aEvent = dummyEvent;	// to get rid of compiler warning
   179 	return EPass;
   180 #else
   181 
   182 	TVerdict result = EFail;
   183 	
   184 	// status of events
   185 	TRequestStatus timerStatus;
   186 	TRequestStatus eventStatus;
   187 
   188 	// due to problems with the timer as a member variable 
   189 	// added a local timer here
   190 	RTimer  myTimer ;
   191 	myTimer.CreateLocal();
   192 	
   193     // create an event and initialise with unknown marker
   194 
   195     TMMFEventPckg receivedEvent;
   196 	
   197 	// for KMaxRetries attempt to find the event
   198 	for( TInt retries = 0; retries < KMaxRetries; retries++ )
   199 		{
   200 		// post receive event to controller
   201 		iController.ReceiveEvents( receivedEvent, eventStatus );
   202 		// start breakout timer to escape
   203 		myTimer.After(timerStatus, KDelay);
   204 		
   205 		// wait for an event to mature
   206 		User::WaitForRequest( eventStatus, timerStatus );
   207 		
   208 		// check if the command is the event 
   209 		// and that a timeout did not occur
   210         if( IsTimeOut( eventStatus ))
   211 			{
   212 			// cancel the receive events
   213 			CancelReceivedEvents();
   214 			}
   215 		else if( IsSoughtEvent( aEvent, receivedEvent ) )
   216 			{
   217 			// cancel the outstanding timer
   218 			User::Check();
   219 			myTimer.Cancel();
   220 			// set status to pass since we have found the event
   221 			result = EPass;
   222 			break;
   223 			}
   224 		else
   225 			{
   226 			// We rx'd an event other than expected
   227 			myTimer.Cancel();
   228 			}
   229 		}
   230 	return result;
   231 #endif // EVENT_SEARCH_DISABLED
   232 	}
   233 
   234 TBool RTestStepMmfCtlfrmAudio::IsTimeOut( TRequestStatus& aEventStatus )
   235 	{
   236     return ( aEventStatus == KRequestPending);
   237 	}
   238 
   239 TBool RTestStepMmfCtlfrmAudio::IsSoughtEvent( TMMFEvent& aExpectedEvent, TMMFEventPckg& aReceivedEvent )
   240 	{
   241 	
   242 	TInt expectedUid = aExpectedEvent.iEventType.iUid;
   243 	TInt receivedUid = aReceivedEvent().iEventType.iUid;
   244 
   245 	// display any events we get
   246 	INFO_PRINTF3(_L("Event received : 0x%08x %d"), 
   247 					 aReceivedEvent().iEventType.iUid, aReceivedEvent().iErrorCode);
   248 
   249 	return ((expectedUid == receivedUid) &&
   250 	 	    (aExpectedEvent.iErrorCode == aReceivedEvent().iErrorCode));
   251 	}
   252 
   253 void RTestStepMmfCtlfrmAudio::CancelReceivedEvents()
   254 	{
   255 	iController.CancelReceiveEvents();
   256 	}
   257 
   258 // ---------------------------
   259 // RTestStepMmfCtlfrmAudioPrimed
   260 // as above, with source / sink handles, primed in preamble
   261 
   262 TVerdict RTestStepMmfCtlfrmAudioPrimed::OpenL()
   263 	{
   264 	// initialise the controller, including adding source and sink; prime it.
   265 	// retain handles to the source and sink so we can verify them after reset
   266 	TInt error = KErrNone;
   267 	TVerdict result = EPass;
   268 
   269 	iSourceHandlePtr = NULL;
   270 	iSinkHandlePtr = NULL;
   271 
   272 	iSettings.iPriority = ETSIMmfPriorityHigh;
   273 	iSettings.iPref = EMdaPriorityPreferenceQuality;
   274 	iSettings.iState = EMMFStateIdle;
   275 
   276 	// Open a controller
   277 	error = iController.Open(KUidCustomTestAudioPlugin, iSettings);
   278 	if (error)
   279 		{
   280 		ERR_PRINTF2(_L("controller failed to open, error %d"), error);
   281 		return iTestStepResult = EInconclusive;
   282 		}
   283 
   284 	INFO_PRINTF2(_L("Opened Custom Audio Controller, UID 0x%8x"), KUidCustomTestAudioPlugin);
   285 	// Add a source and sink
   286 	_LIT(KTestWavFile, "c:\\TsiMmfCtlfrmData\\test.wav");
   287 	iFileConfig().iPath = KTestWavFile;
   288 
   289 	// add a data source with a handle
   290 	iSourceHandlePtr = new (ELeave) TMMFMessageDestination();
   291 	TMMFMessageDestination& sourceHandle = *iSourceHandlePtr;
   292 	error = iController.AddDataSource(KUidMmfFileSource, iFileConfig, sourceHandle);
   293 	if (error)
   294 		{
   295 		ERR_PRINTF2(_L("AddDataSource failed, error %d"), error);
   296 		Close();
   297 		return iTestStepResult = EInconclusive;
   298 		}
   299 
   300 	// add a data sink with a handle
   301 	iSinkHandlePtr = new (ELeave) TMMFMessageDestination();
   302 	TMMFMessageDestination& sinkHandle = *iSinkHandlePtr;
   303 
   304 	error = iController.AddDataSink(KUidMmfAudioOutput, KNullDesC8, sinkHandle);
   305 	if (error)
   306 		{
   307 		ERR_PRINTF2(_L("AddDataSink failed, error %d"), error);
   308 		Close();
   309 		return iTestStepResult = EInconclusive;
   310 		}
   311 
   312 	// prime it
   313 	error = iController.Prime();
   314 	if(error)
   315 		{
   316 		ERR_PRINTF2(_L("Prime failed, error %d"), error);
   317 		Close();
   318 		return iTestStepResult = EInconclusive;
   319 		}
   320 	
   321 	// wait for and process the return event from the custom audio controller
   322 	TMMFEvent primeEvent( KPrimeTestId, KErrNone);
   323 	result = SearchForEvent( primeEvent );
   324 	if( result == EFail )
   325 		{
   326 		ERR_PRINTF1(_L("Custom audio controller did not return a prime event"));
   327 		Close();
   328 		return iTestStepResult = EInconclusive;
   329 		}
   330 
   331 	return iTestStepResult = EPass;
   332 	}
   333 
   334 void RTestStepMmfCtlfrmAudioPrimed::Close() 
   335 	{
   336 	iController.Stop();
   337 	iController.Reset();
   338 	delete iSinkHandlePtr;
   339 	delete iSourceHandlePtr;
   340 	iController.Close();
   341 	// close controller delay - ensure it has time to finish
   342 	// (so we don't get access violation from something trying to dequeue it before it's closed)
   343 	const TTimeIntervalMicroSeconds32 KCloseControllerDelay = 500000L;
   344 	User::After(KCloseControllerDelay);
   345 	}
   346 
   347 
   348 // ---------------------------
   349 // RTestStepMmfCtlfrmAudioNoSource
   350 // same as RTestStepMmfCtlfrmAudio, but has no source or sink loaded yet
   351 TVerdict RTestStepMmfCtlfrmAudioNoSource::OpenL()
   352 	{
   353 	// preamble - load a controller but give it no data source
   354 	TInt error = KErrNone;
   355 
   356 	iSettings.iPriority = ETSIMmfPriorityHigh;
   357 	iSettings.iPref = EMdaPriorityPreferenceQuality;
   358 	iSettings.iState = EMMFStateIdle;
   359 
   360 	// Open a controller
   361 	error = iController.Open(KUidCustomTestAudioPlugin, iSettings);
   362 	if (error)
   363 		{
   364 		ERR_PRINTF2(_L("controller failed to open, error %d"), error);
   365 		return iTestStepResult = EInconclusive;
   366 		}
   367 
   368 	INFO_PRINTF2(_L("Opened Custom Audio Controller, UID 0x%8x"), KUidCustomTestAudioPlugin);
   369 	return iTestStepResult = EPass;
   370 	}
   371 
   372 // ---------------------------
   373 // RTestStepMmfCtlfrmDualAudio
   374 // same as RTestStepMmfCtlfrmAudio, with 2 identical controllers
   375 
   376 TVerdict RTestStepMmfCtlfrmDualAudio::OpenL() 
   377 	{
   378 	TInt error = KErrNone;
   379 
   380 	iSettings.iPriority = ETSIMmfPriorityHigh;
   381 	iSettings.iPref = EMdaPriorityPreferenceTime;
   382 	iSettings.iState = EMMFStateIdle;
   383 
   384 	// Open both controllers
   385 	error = iController1.Open(KUidCustomTestAudioPlugin, iSettings);
   386 	if (error)
   387 		{
   388 		ERR_PRINTF2(_L("iController1 failed to open, error %d"), error);
   389 		return iTestStepResult = EInconclusive;
   390 		}
   391 	INFO_PRINTF2(_L("Controller 1 : Opened Custom Audio Controller, UID 0x%8x"), KUidCustomTestAudioPlugin);
   392 	error = iController2.Open(KUidCustomTestAudioPlugin, iSettings);
   393 	if (error)
   394 		{
   395 		ERR_PRINTF2(_L("iController2 failed to open, error %d"), error);
   396 		Close();
   397 		return iTestStepResult = EInconclusive;
   398 		}
   399 	INFO_PRINTF2(_L("Controller 2 : Opened Custom Audio Controller, UID 0x%8x"), KUidCustomTestAudioPlugin);
   400 
   401 	// Add source and sink
   402 	// Use two different files to avoid conflict
   403 	_LIT(KTestWavFile1, "c:\\TsiMmfCtlfrmData\\test.wav");
   404 	_LIT(KTestWavFile2, "c:\\TsiMmfCtlfrmData\\test2.wav");
   405 	iFileConfig1().iPath = KTestWavFile1;
   406 	iFileConfig2().iPath = KTestWavFile2;
   407 	error = iController1.AddDataSource(KUidMmfFileSource, iFileConfig1);
   408 	if (error)
   409 		{
   410 		ERR_PRINTF2(_L("iController1 failed to add a data source, error %d"), error);
   411 		return iTestStepResult = EInconclusive;
   412 		}
   413 	error = iController1.AddDataSink(KUidMmfAudioOutput, KNullDesC8);
   414 	if (error)
   415 		{
   416 		ERR_PRINTF2(_L("iController1 failed to add a data sink, error %d"), error);
   417 		Close();
   418 		return iTestStepResult = EInconclusive;
   419 		}
   420 	error = iController2.AddDataSource(KUidMmfFileSource, iFileConfig2);
   421 	if (error)
   422 		{
   423 		ERR_PRINTF2(_L("iController2 failed to add a data source, error %d"), error);
   424 		Close();
   425 		return iTestStepResult = EInconclusive;
   426 		}
   427 	error = iController2.AddDataSink(KUidMmfAudioOutput, KNullDesC8);
   428 	if (error)
   429 		{
   430 		ERR_PRINTF2(_L("iController2 failed to add a data sink, error %d"), error);
   431 		Close();
   432 		return iTestStepResult = EInconclusive;
   433 		}
   434 	
   435 	return iTestStepResult = EPass;
   436 	}
   437 
   438 void RTestStepMmfCtlfrmDualAudio::Close() 
   439 	{
   440 	iController1.Stop();
   441 	iController1.Reset();
   442 	iController1.Close();
   443 
   444 	iController2.Stop();
   445 	iController2.Reset();
   446 	iController2.Close();
   447 
   448 	// close controller delay - ensure it has time to finish
   449 	// (so we don't get access violation from something trying to dequeue it before it's closed)
   450 	const TTimeIntervalMicroSeconds32 KCloseControllerDelay = 500000L;
   451 	User::After(KCloseControllerDelay);
   452 	}
   453 
   454 // Searches for an event
   455 TVerdict RTestStepMmfCtlfrmDualAudio::SearchForEvent( TMMFEvent& aEvent, TInt aWhichController )
   456 	{
   457 	// NB don't worry about EVENT_SEARCH_DISABLED here,
   458 	// as generally we'll be looking for events from the Controller Framework here,
   459 	// not from the custom Audio Controller
   460 
   461 	TVerdict result = EFail;
   462 	
   463 	// status of events
   464 	TRequestStatus timerStatus    ;
   465 	TRequestStatus eventStatus    ;
   466 
   467 	RMMFController* theController;
   468 	// which controller are we searching on?
   469 	if(aWhichController == 1)
   470 		theController = &iController1;
   471 	else if(aWhichController == 2)
   472 		theController = &iController2;
   473 	else 
   474 		{
   475 		ERR_PRINTF1(_L("SearchForEvent error : controller must be 1 or 2"));
   476 		return result = EFail;
   477 		}
   478 
   479 	// due to problems with the timer as a member variable 
   480 	// added a local timer here
   481 	RTimer  myTimer ;
   482 	myTimer.CreateLocal();
   483 	
   484     // create an event and initialise with unknown marker
   485 
   486     TMMFEventPckg receivedEvent;
   487 	
   488 	// for KMaxRetries attempt to find the event
   489 	for( TInt retries = 0; retries < KMaxRetries; retries++ )
   490 		{
   491 		// post receive event to controller
   492 		(*theController).ReceiveEvents( receivedEvent, eventStatus );
   493 		// start breakout timer to escape
   494 		myTimer.After( timerStatus, KDelay );
   495 		
   496 		// wait for an event to mature
   497 		User::WaitForRequest( eventStatus, timerStatus );
   498 		
   499 		// check if the command is the event 
   500 		// and that a timeout did not occur
   501         if( IsTimeOut( eventStatus ))
   502 			{
   503 			// cancel the receive events
   504 			CancelReceivedEvents(aWhichController);
   505 			}
   506 		else if( IsSoughtEvent( aEvent, receivedEvent ) )
   507 			{
   508 			// cancel the outstanding timer
   509 			User::Check();
   510 			myTimer.Cancel();
   511 			// set status to pass since we have found the event
   512 			result = EPass;
   513 			break;
   514 			}
   515 		else
   516 			{
   517 			// We rx'd an event other than expected
   518 			myTimer.Cancel();
   519 			}
   520 		}
   521     return result;
   522 	}
   523 
   524 TBool RTestStepMmfCtlfrmDualAudio::IsTimeOut( TRequestStatus& aEventStatus )
   525 	{
   526     return (aEventStatus == KRequestPending);
   527 	}
   528 
   529 TBool RTestStepMmfCtlfrmDualAudio::IsSoughtEvent( TMMFEvent& aExpectedEvent, TMMFEventPckg& aReceivedEvent )
   530 	{
   531 	
   532 	TInt expectedUid = aExpectedEvent.iEventType.iUid;
   533 	TInt receivedUid = aReceivedEvent().iEventType.iUid;
   534 
   535 	// display any events we get
   536 	INFO_PRINTF3(_L("Event expected : 0x%08x %d"), 
   537 				 expectedUid, aExpectedEvent.iErrorCode);
   538 	INFO_PRINTF3(_L("Event received : 0x%08x %d"), 
   539 				 aReceivedEvent().iEventType.iUid, aReceivedEvent().iErrorCode);
   540 
   541 	return ((expectedUid == receivedUid) &&
   542 	 	    (aExpectedEvent.iErrorCode == aReceivedEvent().iErrorCode));
   543 	}
   544 
   545 void RTestStepMmfCtlfrmDualAudio::CancelReceivedEvents(TInt aWhichController)
   546 	{
   547 	RMMFController* theController;
   548 	// which controller are we searching on?
   549 	if(aWhichController == 1)
   550 		theController = &iController1;
   551 	else if(aWhichController == 2)
   552 		theController = &iController2;
   553 	else 
   554 		{
   555 		ERR_PRINTF1(_L("CancelReceivedEvents error : controller must be 1 or 2"));
   556 		return;
   557 		}
   558 	(*theController).CancelReceiveEvents();
   559 	}
   560 
   561 // ---------------------------
   562 // RTestStepMmfCtlfrmVideo
   563 // base class with preamble / postamble to open and close the video controller
   564 // NB we're only actually using this to test custom commands
   565 
   566 TVerdict RTestStepMmfCtlfrmVideo::OpenL() 
   567 	{
   568 	TInt error = KErrNone;
   569 
   570 	iSettings.iPriority = ETSIMmfPriorityHigh;
   571 	iSettings.iPref = EMdaPriorityPreferenceQuality;
   572 	iSettings.iState = EMMFStateIdle;
   573 
   574 	// Open a controller
   575 	error = iController.Open(KMmfVideoTestControllerUid, iSettings);
   576 	if (error)
   577 		{
   578 		ERR_PRINTF2(_L("controller failed to open, error %d"), error);
   579 		return iTestStepResult = EInconclusive;
   580 		}
   581 
   582 	INFO_PRINTF2(_L("Opened Custom Video Controller, UID 0x%8x"), KMmfVideoTestControllerUid);
   583 	// Add a source and sink
   584 	_LIT(KTestAviFile, "c:\\VclntITestData\\LongVideo.avi");
   585 	iFileConfig().iPath = KTestAviFile;
   586 	error = iController.AddDataSource(KUidMmfFileSource, iFileConfig);
   587 	if (error)
   588 		{
   589 		ERR_PRINTF2(_L("failed to add a data source, error %d"), error);
   590 		Close();
   591 		return iTestStepResult = EInconclusive;
   592 		}
   593 	error = iController.AddDataSink(KUidMmfAudioOutput, KNullDesC8);
   594 	if (error)
   595 		{
   596 		ERR_PRINTF2(_L("failed to add a data sink, error %d"), error);
   597 		Close();
   598 		return iTestStepResult = EInconclusive;
   599 		}
   600 	
   601 	return iTestStepResult = EPass;
   602 	}
   603 
   604 void RTestStepMmfCtlfrmVideo::Close() 
   605 	{
   606 	iController.Stop();
   607 	iController.Reset();
   608 	iController.Close();
   609 	// close controller delay - ensure it has time to finish
   610 	// (so we don't get access violation from something trying to dequeue it before it's closed)
   611 	const TTimeIntervalMicroSeconds32 KCloseControllerDelay = 500000L;
   612 	User::After(KCloseControllerDelay);
   613 	}
   614