os/mm/devsound/sounddevbt/src/swcodecwrapper/mmfBtSwCodecWrapper.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 // Copyright (c) 2005-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 #include "mmfbtswcodecwrapper.h"
    17 #include "mmfBtSwCodecPlayDataPath.h"
    18 #include "mmfBtSwCodecRecordDataPath.h"
    19 #include "mmfBtSwCodecConvertDataPath.h"
    20 #include <mmfswcodecwrappercustominterfacesuids.hrh>
    21 #include "mmfBtswcodecwrapperCustomInterfaces.h"
    22 #include "MMFBtRoutingSoundDevice.h"
    23 #include <mmfpaniccodes.h>
    24 
    25 
    26 /*
    27  *	AO to handle RSD initialisation
    28  *
    29  */
    30 CRoutingSoundDeviceOpenHandler* CRoutingSoundDeviceOpenHandler::NewL(CMMFSwCodecWrapper* aObserver)
    31 	{
    32 	CRoutingSoundDeviceOpenHandler* self = new(ELeave) CRoutingSoundDeviceOpenHandler(aObserver);
    33 	CleanupStack::PushL(self);
    34 	self->ConstructL();
    35 	CleanupStack::Pop(self);
    36 	return self;
    37 	}
    38 	
    39 CRoutingSoundDeviceOpenHandler::~CRoutingSoundDeviceOpenHandler()
    40 	{
    41 	Cancel();
    42 	}
    43 		
    44 void CRoutingSoundDeviceOpenHandler::RunL()
    45 	{
    46 	TInt err = iStatus.Int();
    47 	if (iObserver)
    48 		{
    49 		iObserver->OpenComplete(err);
    50 		}
    51 	}
    52 	
    53 void CRoutingSoundDeviceOpenHandler::DoCancel()
    54 	{
    55 	if (iObserver)
    56 		{
    57 		iObserver->OpenComplete(KErrCancel);
    58 		}
    59 	}
    60 	
    61 CRoutingSoundDeviceOpenHandler::CRoutingSoundDeviceOpenHandler(CMMFSwCodecWrapper* aObserver) :
    62 															 	CActive(EPriorityStandard),
    63 															 	iObserver(aObserver)								 	
    64 														
    65 	{
    66 	CActiveScheduler::Add(this);	
    67 	}
    68 	
    69 void CRoutingSoundDeviceOpenHandler::ConstructL()
    70 	{
    71 	}
    72 
    73 void CRoutingSoundDeviceOpenHandler::Start()
    74 	{
    75 	if (!IsActive())
    76 		{
    77 		SetActive();
    78 		}
    79 	}
    80  
    81 
    82 /**
    83  * Internal panic
    84  * @internalComponent
    85  */
    86 void Panic(TInt aPanicCode)
    87 	{
    88 	_LIT(KMMFSwCodecWrapperPanicCategory, "MMFSwCodecWrapper");
    89 	User::Panic(KMMFSwCodecWrapperPanicCategory, aPanicCode);
    90 	}
    91 
    92 
    93 /**
    94  * This method is not be exported as it is only 
    95  * intended to be called within this DLL.
    96  * It's purpose is to assign an CRoutingSoundPlayDevice to the play
    97  * custom interface
    98  * @internalComponent
    99  */
   100 void TPlayCustomInterface::SetDevice(CRoutingSoundPlayDevice* aDevice)
   101 	{
   102 	iDevice = aDevice;
   103 	}
   104 
   105 void TPlayCustomInterface::SetVolume(TUint aVolume)
   106 	{
   107 	iVolume = aVolume;
   108 	if (iDevice && iDevice->Handle())
   109 		{
   110 		iDevice->SetVolume(iVolume);
   111 		}
   112 	}
   113 
   114 /**
   115  * Procedure to get the number of bytes played by the device driver
   116  * If there is no handle available to the device driver then the 
   117  * procedure returns the last known value
   118  * @prototype
   119  * @return number of bytes played
   120  */
   121 TUint TPlayCustomInterface::BytesPlayed()
   122 	{
   123 	if(iDevice)
   124 		{
   125 		if (iDevice->Handle())
   126 			{
   127 			iBytesPlayed = iDevice->BytesPlayed();
   128 			}
   129 		}
   130 	return iBytesPlayed;
   131 	}
   132 	
   133 TTaskConfig TPlayCustomInterface::Caps()
   134 	{
   135 	TTaskConfig taskConfig;
   136 	taskConfig.iRate = 0;
   137 	taskConfig.iStereoMode = 0;
   138 	taskConfig.iUid = KUidRefDevSoundTaskConfig;
   139 	
   140 	if (iDevice && iDevice->Handle())
   141 		{
   142 		RArray<TUint> supportedSampleRates;
   143 		RArray<TRange>supportedRateRanges;
   144 		iDevice->GetSupportedSampleRates(supportedSampleRates,supportedRateRanges);	
   145 		for (TUint i=0; i<supportedSampleRates.Count(); i++)
   146 			{
   147 			switch(supportedSampleRates[i])
   148 				{
   149 				case 8000:
   150 					taskConfig.iRate |= ETask8000Hz;
   151 					break;
   152 				case 11025:
   153 					taskConfig.iRate |= ETask11025Hz;
   154   					break;
   155 				case 12000:
   156 					taskConfig.iRate |= ETask12000Hz;
   157 					break;
   158 				case 16000:
   159 					taskConfig.iRate |= ETask16000Hz;
   160 					break;
   161 				case 22050:
   162   					taskConfig.iRate |= ETask22050Hz;
   163   					break;
   164 				case 24000:
   165   					taskConfig.iRate |= ETask24000Hz;
   166   					break;
   167 				case 32000:
   168   					taskConfig.iRate |= ETask32000Hz;
   169   					break;
   170 				case 44100:
   171 					taskConfig.iRate |= ETask44100Hz;
   172   					break;
   173 				case 48000:
   174 					taskConfig.iRate |= ETask48000Hz;
   175 					break;
   176 				case 88200:
   177 					taskConfig.iRate |= ETask88200Hz;
   178 					break;
   179 				case 96000:
   180 					taskConfig.iRate |= ETask96000Hz;
   181 					break;
   182 				default: //do nothing
   183 					break;	
   184 				}//	switch(supportedSampleRates[i])
   185 			supportedSampleRates.Close();
   186 			supportedRateRanges.Close();
   187 			}//for (TUint i=0; i<supportedSampleRates.Count(); i++)
   188 		RArray<TUint> supportedChannels;
   189 		TMMFStereoSupport stereoSupport;
   190 		iDevice->GetSupportedChannels(supportedChannels,stereoSupport);	
   191 		for (TUint i=0; i<supportedChannels.Count(); i++)
   192 			{//note we don't have a TaskConfig enum for Joint stereo
   193 			switch(supportedChannels[i])
   194 				{
   195 				case EMMFMono:
   196 					taskConfig.iStereoMode |= ETaskMono;
   197 					break;
   198 				case EMMFStereo:
   199 					if (stereoSupport == EMMFInterleavedOnly)
   200 						{
   201 						taskConfig.iStereoMode |= ETaskInterleaved;
   202 						}
   203 					else if (stereoSupport == EMMFNonInterleavedOnly)
   204 						{
   205 						taskConfig.iStereoMode |= ETaskNonInterleaved;
   206 						}
   207 					else if (stereoSupport == EMMFBothNonAndInterleaved)
   208 						{
   209 						taskConfig.iStereoMode |= (ETaskInterleaved|ETaskNonInterleaved);
   210 						}
   211 					break;
   212 				default://do nothing
   213 					break;
   214 				}//switch(supportedChannels[i])
   215 			supportedChannels.Close();
   216 			}//	for (TUint i=0; i<supportedChannels.Count(); i++)
   217 		}//if (iDevice && iDevice->Handle())
   218 	return taskConfig;
   219 	}
   220 
   221 /**
   222  * Procedure to get the number of bytes recorded by the device  
   223  * @prototype
   224  * @return number of bytes recorded
   225  */
   226 TUint TRecordCustomInterface::BytesRecorded()
   227 	{
   228 	if(iDataPath)
   229 		{
   230 		iBytesRecorded = iDataPath->RecordedBytesCount();
   231 		}
   232 	return iBytesRecorded;
   233 	}
   234 
   235 /**
   236 Constructor.
   237 */
   238 EXPORT_C CMMFSwCodecWrapper::CMMFSwCodecWrapper()
   239 	{
   240 	}
   241 
   242 /**
   243 Destructor.
   244 
   245 The destructor is called by ECom framework allowing derived classes
   246 to clean up implementation specific resources. The sound
   247 device drivers are freed.
   248 */
   249 EXPORT_C CMMFSwCodecWrapper::~CMMFSwCodecWrapper()
   250 	{
   251 	// AO to handle OpenDevice call
   252 	if (iOpenHandler && iOpenHandler->IsActive())
   253 		{
   254 		iOpenHandler->Cancel();	
   255 		}
   256 	delete iOpenHandler;
   257 	delete iRecordDevice;
   258 	delete iPlayDevice;
   259 	delete iDataPath;
   260 	delete iCodec;
   261 	delete iPlayCustomInterface;
   262 	delete iRecordCustomInterface;
   263 	}
   264 	
   265 /**
   266 Initializes the hardware device tasks - in the case of a
   267 sw codec wrapper 'hardware device' this consists of loading the
   268 sound device drivers and creating the CMMFSwCodec.
   269 
   270 @param  aDevInfo
   271         Device initialization parameters.
   272         Only the iHwDeviceObserver is used for CMFSwCodecWrapper
   273         derived CMMFHwDevices.
   274 @return An error code indicating if the function call was successful. KErrNone on success, otherwise
   275         another of the system-wide error codes.
   276 */
   277 EXPORT_C TInt CMMFSwCodecWrapper::Init(THwDeviceInitParams& aDevInfo)
   278 	{
   279 	TRequestStatus status;
   280 	Init(aDevInfo,status);
   281 	User::WaitForRequest(status);
   282 	return status.Int();
   283 	}
   284 
   285 
   286 /**
   287 Initializes the hardware device tasks - in the case of a
   288 sw codec wrapper 'hardware device' this consists of loading the
   289 sound device drivers and creating the CMMFSwCodec.
   290 
   291 @param  aDevInfo
   292         Device initialization parameters.
   293         Only the iHwDeviceObserver is used for CMFSwCodecWrapper
   294         derived CMMFHwDevices.
   295 @param	aStatus
   296 		Status flag belonging to an Active Object that will have its
   297 		RunL() called when this function completes
   298 */
   299 EXPORT_C void CMMFSwCodecWrapper::Init(	THwDeviceInitParams &aDevInfo,
   300 										TRequestStatus& aStatus)
   301 	{
   302 	aStatus = KRequestPending;
   303 	TRequestStatus* status = &aStatus;
   304 	if (!aDevInfo.iHwDeviceObserver)
   305 		{
   306 		User::RequestComplete(status, KErrArgument);
   307 		return;
   308 		}
   309 	iHwDeviceObserver = aDevInfo.iHwDeviceObserver;
   310 
   311 	TInt err = KErrNone;
   312 	if (aDevInfo.iOutStream.iConnection.iId)
   313 		{
   314 		iDeviceUid = TUid::Uid(aDevInfo.iOutStream.iConnection.iId);
   315 		// Play device
   316 		delete iPlayDevice;
   317 		iPlayDevice  = NULL;
   318 		TRAP(err, iPlayDevice = CRoutingSoundPlayDevice::NewL());
   319 		if (err == KErrNone)
   320 			{
   321 			iPlayDevice->Initialize(iDeviceUid,
   322 									aDevInfo.iOutStream.iDeviceName, *status);
   323 			if (!iPlayCustomInterface)
   324 				{
   325 				TRAP(err,iPlayCustomInterface = new(ELeave)TPlayCustomInterface());
   326 				if (err)
   327 					{
   328 					delete iPlayDevice;
   329 					iPlayDevice = NULL;
   330 					User::RequestComplete(status, err);
   331 					return;
   332 					}
   333 				}
   334 			static_cast<TPlayCustomInterface*>(iPlayCustomInterface)->SetDevice(iPlayDevice);	
   335 			}
   336 		}
   337 	if (aDevInfo.iInStream.iConnection.iId)
   338 		{
   339 		iDeviceUid = TUid::Uid(aDevInfo.iInStream.iConnection.iId);
   340 			// Record device
   341 		TRAP(err, iRecordDevice = CRoutingSoundRecordDevice::NewL());
   342 		if (err == KErrNone)
   343 			{
   344 			iRecordDevice->Initialize(iDeviceUid, KNullDesC8, *status);
   345 			if (!iRecordCustomInterface)
   346 				{
   347 				TRAP(err,iRecordCustomInterface = new(ELeave)TRecordCustomInterface());
   348 				if (err)
   349 					{
   350 					delete iRecordDevice;
   351 					iRecordDevice = NULL;
   352 					User::RequestComplete(status, err);
   353 					return;
   354 					}
   355 				}
   356 			}
   357 		}
   358 	
   359 	iCodec = &(Codec()); //create codec
   360 		
   361 	//[ assert the post condition ]
   362 	if (!iCodec)
   363 		{
   364 		err = KErrNotSupported;
   365 		}
   366 
   367 	if (err != KErrNone)
   368 		{
   369 		User::RequestComplete(status, err);
   370 		// Cancel initialisation too
   371 		if (aDevInfo.iOutStream.iConnection.iId)
   372 			{
   373 			iPlayDevice->CancelInitialize(iDeviceUid);
   374 			}
   375 		if (aDevInfo.iInStream.iConnection.iId)
   376 			{
   377 			iRecordDevice->CancelInitialize(iDeviceUid);
   378 			}		
   379 		}		
   380 	else if ((!aDevInfo.iOutStream.iConnection.iId)&& (!aDevInfo.iInStream.iConnection.iId))
   381 		{
   382 		//could be used for conversion so complete the request status
   383 		User::RequestComplete(status, KErrNone);
   384 		}
   385 		
   386 	}
   387 
   388 /**
   389 Starts Encoding or Decoding task(s) based on the parameter specified.
   390 
   391 @param  aFuncCmd
   392         The device function specifying the requested service i.e. decode or encode
   393         where EDevEncode = Record, EDevDecode = Play and EDevNullFunc = Convert.
   394 @param  aFlowCmd
   395         The device flow directions for requested service.
   396         This parameter is ignored for CMMFSwCodecWrapper CMMFHwDevicePlugins
   397 @return An error code indicating if the function call was successful. KErrNone on success, otherwise
   398         another of the system-wide error codes.
   399 */
   400 EXPORT_C TInt CMMFSwCodecWrapper::Start(TDeviceFunc aFuncCmd, TDeviceFlow /*aFlowCmd*/)
   401 	{
   402 	TInt error = KErrNone;
   403 
   404 	// [ precondition that aFuncCmd is valid]
   405 	if (!((aFuncCmd == EDevEncode)|(aFuncCmd == EDevDecode)|(aFuncCmd == EDevNullFunc)))
   406 		{
   407 		return KErrArgument;
   408 		}
   409 
   410 	// [ precondition that iCodec is present]
   411 	if (!iCodec)
   412 		{
   413 		return KErrNotReady; //make sure the codec has been added
   414 		}
   415 
   416     switch (aFuncCmd)
   417         {
   418         case EDevEncode: // Audio record
   419 			{
   420 			error = StartEncode();
   421 			}
   422             break;
   423         case EDevDecode: // Audio play
   424 			{
   425 			error = StartDecode();
   426 			}
   427             break;
   428 		case EDevNullFunc: //Audio Convert
   429 			{
   430 			error = StartConvert();
   431 			}
   432 			break;
   433         default:
   434             error = KErrNotSupported;
   435             break;
   436 		}
   437 
   438 	//[ assert the post conditions ]
   439 #ifdef DEBUG
   440 	if (!error)
   441 		{//only assert if no error otherwise post consitions not valid
   442 		__ASSERT_DEBUG(iDataPath, Panic(EMMFSwCodecWrapperNoDataPath));
   443 		if ((aFuncCmd == EDevEncode)||(aFuncCmd == EDevDecode))
   444 			{
   445 			__ASSERT_DEBUG(iDataPath->Device().Handle(), Panic(EMMFSwCodecWrapperNoDevice));
   446 			}
   447 		}
   448 #endif
   449 
   450 	return error;
   451 	}
   452 
   453 // Use AO to OpenDevice
   454 TInt CMMFSwCodecWrapper::StartDecode()
   455 	{
   456 	TInt error = KErrNone;
   457 
   458 	//[ assert precondition that play custom interface is present]
   459 	//if there is no play custom interface then the user of the CMMFSwCodecWrapper
   460 	//cannot have set any of the custom settings such as sample rate.
   461 	if (!iPlayCustomInterface)
   462 		{
   463 		return KErrNotReady;
   464 		}
   465 
   466 	//play
   467 	if (!iDataPath)
   468 		{//create a datapath
   469 		TRAP(error,iDataPath = CMMFSwCodecPlayDataPath::NewL(iPlayDevice, iDeviceUid));
   470 		if ((iDataPath) && (error == KErrNone))
   471 			{
   472 			iDataPath->SetObserver(*iHwDeviceObserver);
   473 			error = iDataPath->AddCodec(*iCodec);
   474 			iDeviceBufferSize = iCodec->SinkBufferSize();
   475 			static_cast<CMMFSwCodecPlayDataPath*>(iDataPath)->SetPlayCustomInterface(*iPlayCustomInterface);
   476 			static_cast<CMMFSwCodecPlayDataPath*>(iDataPath)->SetConfigForAudioRamp(iSampleRate, iChannels);
   477 			}
   478 		}
   479 
   480 	if ((error == KErrNone) &&
   481 		(iDataPath->State() != CMMFSwCodecDataPath::EPlaying))
   482 		{
   483 		TBool asynchOpen = EFalse;	// Ensure we only call OpenPlayComplete once
   484 		//datapath was created ok and we are not playing
   485 		if (iDataPath->State() == CMMFSwCodecDataPath::EStopped)
   486 			{
   487 			//starting from 'fresh so set sound device settings
   488   				
   489 			// Create the AO OpenDevice handler
   490 			if (!iOpenHandler)
   491 				{
   492 				TRAP(error, iOpenHandler = CRoutingSoundDeviceOpenHandler::NewL(this));				
   493 				}
   494 			if (!error)
   495 				{
   496  				asynchOpen = ETrue;
   497  				iPlayDevice->SetBufferSize(iDeviceBufferSize);
   498 				iOpenHandler->Start();
   499 	 			static_cast<CMMFSwCodecPlayDataPath*>(iDataPath)->Device()->
   500  										OpenDevice(iDeviceUid, iOpenHandler->iStatus);
   501 				}
   502 			}
   503 		if (!asynchOpen)
   504 			{
   505 			error = OpenPlayComplete(error);
   506 			}
   507 
   508 		}//status == KErrNone
   509 
   510 	return error;
   511 	}
   512 
   513 TInt CMMFSwCodecWrapper::StartEncode()
   514 	{//record
   515 
   516 	//[ assert precondition that record custom interface is present]
   517 	//if there is no record custom interface then the user of the CMMFSwCodecWrapper
   518 	//cannot have set any of the custom settings such as sample rate.
   519 	if (!iRecordCustomInterface)
   520 		{
   521 		return KErrNotReady;
   522 		}
   523 
   524 	TInt error = KErrNone;
   525 	if (!iDataPath)
   526 		{
   527 		TRAP(error,iDataPath = CMMFSwCodecRecordDataPath::NewL(iRecordDevice));
   528 		if ((iDataPath)&&(error == KErrNone))
   529 			{
   530 			iDataPath->SetObserver(*iHwDeviceObserver);
   531 			error = iDataPath->AddCodec(*iCodec);
   532 			iDeviceBufferSize = (iCodec->SourceBufferSize());
   533 			static_cast<TRecordCustomInterface*>(iRecordCustomInterface)->SetDataPath(static_cast<CMMFSwCodecRecordDataPath*>(iDataPath));
   534 			}
   535 		}
   536 	if ((error == KErrNone)&&
   537 		(iDataPath->State() != CMMFSwCodecDataPath::EPlaying))
   538 		{
   539 		TBool asynchOpen = EFalse;	// Ensure we only call OpenPlayComplete once
   540 		if (!(static_cast<CMMFSwCodecRecordDataPath*>(iDataPath))->Device()->Handle())
   541   			{
   542 			// Create the AO OpenDevice handler
   543 			if (!iOpenHandler)
   544 				{
   545 				TRAP(error, iOpenHandler = CRoutingSoundDeviceOpenHandler::NewL(this));				
   546 				}
   547 			if (!error)
   548 				{
   549 				asynchOpen = ETrue;
   550 				iRecordDevice->SetBufferSize(iDeviceBufferSize);
   551 				iOpenHandler->Start();
   552  				static_cast<CMMFSwCodecRecordDataPath*>(iDataPath)->Device()->
   553 									OpenDevice(iDeviceUid, iOpenHandler->iStatus);
   554 				}
   555 			}
   556 			
   557 		if (!asynchOpen)
   558 			{
   559 			error = OpenRecordComplete(error);
   560 			}			
   561 		}
   562 
   563 	return error;
   564 	}
   565 
   566 TInt CMMFSwCodecWrapper::StartConvert()
   567 	{//convert
   568 
   569 	TInt error = KErrNone;
   570 	if (!iDataPath)
   571 		{
   572 		TRAP(error,iDataPath = CMMFSwCodecConvertDataPath::NewL());
   573 		if ((iDataPath)&&(error == KErrNone))
   574 			{
   575 			iDataPath->SetObserver(*iHwDeviceObserver);
   576 			error = iDataPath->AddCodec(*iCodec);
   577 			}
   578 		}
   579     if (error == KErrNone)
   580     	{
   581 		error = iDataPath->Start();
   582     	}
   583 	return error;
   584 	}
   585 
   586 /**
   587 Temporarily suspends the current task of decoding or encoding.
   588 
   589 @return An error code indicating if the function call was successful. KErrNone on success, otherwise
   590         another of the system-wide error codes.
   591 */
   592 EXPORT_C TInt CMMFSwCodecWrapper::Pause()
   593 	{
   594 	// [ precondition that datapath exists ]
   595 	if (!iDataPath)
   596 		{
   597 		return KErrNotReady;
   598 		}
   599 		
   600 	iDataPath->Pause();
   601 	return KErrNone;
   602 	}
   603 
   604 /**
   605 Stops the current on-going task.
   606 
   607 @return An error code indicating if the function call was successful. KErrNone on success, otherwise
   608         another of the system-wide error codes.
   609 */
   610 EXPORT_C TInt CMMFSwCodecWrapper::Stop()
   611 	{
   612 	// [ precondition that datapath exists ]
   613 	if (!iDataPath)
   614 		{
   615 		return KErrNotReady;
   616 		}
   617 	iDataPath->Stop();
   618 	return KErrNone;
   619 	}
   620 
   621 
   622 /**
   623 Stops and deletes the codec.
   624 
   625 This default implementation simply calls DeleteCodec() and then Stop()
   626 but real hardware devices might use this method to free up resources.
   627 
   628 @return An error code indicating if the function call was successful. KErrNone on success, otherwise
   629         another of the system-wide error codes.
   630 */
   631 EXPORT_C TInt CMMFSwCodecWrapper::StopAndDeleteCodec()
   632 	{
   633 	TInt stopError = Stop();
   634 	TInt deleteError = DeleteCodec();
   635 
   636 	if (stopError != KErrNone)
   637 		{
   638 		return stopError;
   639 		}
   640 	else
   641 		{
   642 		return deleteError;
   643 		}
   644 	}
   645 
   646 /**
   647 Deletes the codec
   648 This default implementation does nothing
   649 but real hardware devices might use this method to free up resources.
   650 @return		Error code. KErrNone if successful
   651 */
   652 EXPORT_C TInt CMMFSwCodecWrapper::DeleteCodec()
   653 	{
   654 	return KErrNone;
   655 	}
   656 
   657 /**
   658 Call this function to notify hardware device implementation that
   659 data is available in aFillBufferPtr for decoding.
   660 
   661 @param aFillBufferPtr
   662        The data buffer filled by the observer.
   663 
   664 @return An error code indicating if the function call was successful. KErrNone on success, otherwise
   665         another of the system-wide error codes.
   666 */
   667 EXPORT_C TInt CMMFSwCodecWrapper::ThisHwBufferFilled(CMMFBuffer& aFillBufferPtr)
   668 	{
   669 	TRAPD(err,iDataPath->BufferFilledL(STATIC_CAST(CMMFDataBuffer&, aFillBufferPtr)));
   670 	return err;
   671 	}
   672 
   673 /**
   674 Call this function to notify hardware device implementation that
   675 data in aEmptyBufferPtr from encoding is processed.
   676 
   677 @param  aBuffer
   678         The data buffer processed by observer.
   679 
   680 @return An error code indicating if the function call was successful. KErrNone on success, otherwise
   681         another of the system-wide error codes.
   682 */
   683 EXPORT_C TInt CMMFSwCodecWrapper::ThisHwBufferEmptied(CMMFBuffer& aBuffer)
   684 	{
   685 	TRAPD(err,iDataPath->BufferEmptiedL(STATIC_CAST(CMMFDataBuffer&, aBuffer)));
   686 	return err;
   687 	}
   688 
   689 
   690 /**
   691 Retrieves a custom interface to the device.
   692 The reference CMMFSwCodecWrapper supports two standard custom interfaces,
   693 TPlayCustomInterface and TRecordCustomInterface.
   694 
   695 @param	aInterface
   696 		Interface UID, defined with the custom interface.
   697 		aInterface = KMmfPlayCustomInterface for TPlayCustomInterface,
   698 		aInterface = KMmfRecordCustomInterface for TRecordCustomInterface.
   699 		Actual device implementations of CMMFSwCodecWrapper may do this differently however.
   700 @return A pointer to the interface implementation, or NULL if the device can not
   701 		implement the interface requested. The return value must be cast to the
   702 		correct type by the user.
   703 */
   704 EXPORT_C TAny* CMMFSwCodecWrapper::CustomInterface(TUid aInterface)
   705 	{
   706 	TAny* ret = NULL;
   707 	TInt err = KErrNone;
   708 	if (aInterface.iUid == KMmfPlaySettingsCustomInterface)
   709 		{
   710 		if (!iPlayCustomInterface)
   711 			{
   712 			TRAP(err,iPlayCustomInterface = new(ELeave)TPlayCustomInterface());
   713 			}
   714 		if (err)
   715 			{
   716 			ret = NULL;
   717 			}
   718 		else
   719 			{
   720 			ret = static_cast<TAny*>(iPlayCustomInterface);
   721 			}
   722 		}
   723 	else if (aInterface.iUid == KMmfRecordSettingsCustomInterface)
   724 		{
   725 		if (!iRecordCustomInterface)
   726 			{
   727 			TRAP(err,iRecordCustomInterface = new(ELeave)TRecordCustomInterface());
   728 			}
   729 		if (err)
   730 			{
   731 			ret = NULL;
   732 			}
   733 		else
   734 			{
   735 			ret = static_cast<TAny*>(iRecordCustomInterface);
   736 			}
   737 		}
   738 
   739 	return ret;
   740 	}
   741 
   742 
   743 /**
   744 Used to configure the sample rate and stereo mode of a CMMFHwDevice plugin.
   745 
   746 The configuration of HwDevices is device specific and is not used in any of the reference
   747 devices that return KErrNotSupported.
   748 
   749 @param  aConfig
   750         The device configuration.
   751 */
   752 EXPORT_C TInt CMMFSwCodecWrapper::SetConfig(TTaskConfig& aConfig)
   753 	{
   754 	TInt err = KErrNone;
   755 	if (aConfig.iUid != KUidRefDevSoundTaskConfig)
   756 		return KErrArgument;
   757 	iSampleRate = aConfig.iRate;//note we're cheating a bit
   758 	//iRate is actually a bit map enum but an actual value
   759 	//is more useful here
   760 	TMMFStereoSupport stereoSupport = EMMFNone;
   761 	if (aConfig.iStereoMode == ETaskMono)
   762 		{
   763 		iChannels = 1;
   764 		}
   765 	else if (aConfig.iStereoMode == ETaskInterleaved) 
   766 		{
   767 		iChannels = 2;
   768 		stereoSupport = EMMFInterleavedOnly;
   769 		}
   770 	else //don't support non interleaved
   771 		{
   772 		return KErrNotSupported;
   773 		}
   774 		
   775 	//set values on routing sound device
   776 	if (iPlayDevice)
   777 		{
   778 		err = iPlayDevice->SetChannels(iChannels, stereoSupport);
   779 		if (!err)
   780 			{
   781 			err = iPlayDevice->SetSampleRate(iSampleRate);
   782 			}
   783 		if (!err)
   784 			{//we'll set the data type while were at it for now pcm16 only
   785 			TFourCC fourCC = KMMFFourCCCodePCM16;
   786 			err = iPlayDevice->SetDataType(fourCC);
   787 			}
   788 		}
   789 	if ((iRecordDevice) && (!err))
   790 		{
   791 		err = iRecordDevice->SetChannels(iChannels, stereoSupport);
   792 		if (!err)
   793 			{
   794 			err = iRecordDevice->SetSampleRate(iSampleRate);
   795 			}
   796 		}
   797 	
   798 	return err;
   799 	}
   800 
   801 /**
   802 Callback once CRoutingSoundPlayDevice or CRoutingSoundRecordDevice::Open has completed or continuation from
   803 call to StartDecode / StartEncode, depending on the state.
   804 
   805 @internalTechnology
   806 @param	aError
   807 		The status of the device.
   808 @return A standard Symbian wide error code.
   809  */
   810 TInt CMMFSwCodecWrapper::OpenComplete(TInt aError)
   811 	{
   812 	TInt err = KErrNotSupported;	//
   813 	if (iPlayDevice)
   814 		{
   815 		err = OpenPlayComplete(aError);
   816 		}
   817 	else if (iRecordDevice)
   818 		{
   819 		err = OpenRecordComplete(aError);
   820 		}
   821 	return err;
   822 	}
   823 	
   824 /**
   825 Callback once CRoutingSoundPlayDevice::Open has completed or continuation from
   826 call to StartDecode, depending on the state.
   827 
   828 @param	aError
   829 		The status of the device.
   830 @return A standard Symbian wide error code.
   831  */
   832 TInt CMMFSwCodecWrapper::OpenPlayComplete(TInt aError)
   833 	{
   834 	TInt error = aError;
   835 	
   836 	//datapath was created ok and we are not playing
   837 	if (error == KErrNone && iDataPath->State() == CMMFSwCodecDataPath::EStopped)
   838 		{
   839 		//starting from fresh so set sound device settings
   840 //		static_cast<TPlayCustomInterface*>(iPlayCustomInterface)->SetDevice(
   841 //					static_cast<CMMFSwCodecPlayDataPath*>(iDataPath)->Device() );
   842 		static_cast<CMMFSwCodecPlayDataPath*>(iDataPath)->Device()->SetVolume(iPlayCustomInterface->Volume());
   843 		}
   844 		
   845 	// resuming from pause or ready to play
   846 	if ((error == KErrNone) || (error == KErrInUse))
   847 		{
   848 		error = iDataPath->Start();
   849 		}		
   850 	
   851 	return error;
   852 	}
   853 
   854 /**
   855 Callback once CRoutingSoundRecordDevice::Open has completed or continuation from
   856 call to StartDecode, depending on the state.
   857 
   858 @param	aError
   859 		The status of the device.
   860 @return A standard Symbian wide error code.
   861  */
   862 TInt CMMFSwCodecWrapper::OpenRecordComplete(TInt aError)
   863 	{
   864 	TInt error = aError;
   865 	
   866 	//datapath was created ok and we are not playing
   867 	if (error == KErrNone && iDataPath->State() == CMMFSwCodecDataPath::EStopped)
   868 		{
   869 		//set sound driver settings
   870 		static_cast<CMMFSwCodecRecordDataPath*>(iDataPath)->Device()
   871 												->SetGain(iRecordCustomInterface->Gain());
   872 		/*
   873 		// Sample rate
   874 		(static_cast<CMMFSwCodecRecordDataPath*>(iDataPath))->Device()->SetSampleRate(iSampleRate);
   875 		// Channels
   876 		TMMFStereoSupport stereoSupport = EMMFNone;	// assume mono
   877 		if (iChannels == 2)
   878 			{
   879 			// Assume interleaved only
   880 			stereoSupport = EMMFInterleavedOnly;
   881 			}
   882 		error = (static_cast<CMMFSwCodecRecordDataPath*>(iDataPath))->Device()->SetChannels(iChannels, stereoSupport);
   883 		*/
   884 		}
   885 
   886 	// resuming from pause or ready to play
   887 	if ((error == KErrNone) || (error == KErrInUse))
   888 		{
   889 		error = iDataPath->Start();
   890 		}		
   891 	
   892 	return error;
   893 	}