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