os/mm/mmhais/refacladapt/src/tonehwdevice/tonedatapath.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) 2003-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 "tonedatapath.h"
sl@0
    17
sl@0
    18
sl@0
    19
CToneDataPath* CToneDataPath::NewL()
sl@0
    20
	{
sl@0
    21
	CToneDataPath* self = new(ELeave) CToneDataPath;
sl@0
    22
	CleanupStack::PushL(self);
sl@0
    23
	self->ConstructL();
sl@0
    24
	CleanupStack::Pop();
sl@0
    25
	return self;
sl@0
    26
	}
sl@0
    27
sl@0
    28
sl@0
    29
void CToneDataPath::ConstructL()
sl@0
    30
	{
sl@0
    31
	iAudioPlayer = new (ELeave) CToneDataPathPlayer(*this,CActive::EPriorityUserInput);
sl@0
    32
	iSoundDeviceErrorReceiver = new (ELeave) CToneSoundDevPlayErrorReceiver(*this, CActive::EPriorityUserInput);
sl@0
    33
	}
sl@0
    34
sl@0
    35
sl@0
    36
CToneDataPath::~CToneDataPath()
sl@0
    37
	{
sl@0
    38
	delete iAudioPlayer;
sl@0
    39
	delete iSoundDeviceErrorReceiver;
sl@0
    40
	
sl@0
    41
	iSoundDevice.Close();
sl@0
    42
sl@0
    43
	if (iCodec)
sl@0
    44
		{
sl@0
    45
		delete iSourceBuffer;
sl@0
    46
		if (!iCodec->IsNullCodec()) 
sl@0
    47
			{
sl@0
    48
			delete iSoundDeviceBuffer;
sl@0
    49
			}
sl@0
    50
		}
sl@0
    51
sl@0
    52
#ifdef __USE_MMF_TRANSFERBUFFERS__
sl@0
    53
	delete iTransferWindow;
sl@0
    54
sl@0
    55
	if(iTransferBuffer)
sl@0
    56
		{
sl@0
    57
		iTransferBuffer->Close();
sl@0
    58
		delete iTransferBuffer;
sl@0
    59
		}
sl@0
    60
#endif
sl@0
    61
sl@0
    62
#ifdef __USE_MMF_PTRBUFFERS__
sl@0
    63
	delete iPtrBufferMemoryBlock;
sl@0
    64
#endif
sl@0
    65
	}
sl@0
    66
sl@0
    67
sl@0
    68
TInt CToneDataPath::SetObserver(MMMFHwDeviceObserver& aObserver)
sl@0
    69
	{
sl@0
    70
	TInt error;
sl@0
    71
	if (iHwDeviceObserver)
sl@0
    72
		{
sl@0
    73
		error =  KErrAlreadyExists;
sl@0
    74
		}
sl@0
    75
	else
sl@0
    76
		{
sl@0
    77
		iHwDeviceObserver = &aObserver;
sl@0
    78
		error  = KErrNone;
sl@0
    79
		}
sl@0
    80
	return error;
sl@0
    81
	}
sl@0
    82
sl@0
    83
sl@0
    84
TInt CToneDataPath::AddCodec(CToneCodec& aCodec)
sl@0
    85
	{
sl@0
    86
	if (iCodec)
sl@0
    87
		{
sl@0
    88
		return KErrNotSupported; //doesn't support multiple codecs
sl@0
    89
		}
sl@0
    90
sl@0
    91
	TInt err = KErrNone;
sl@0
    92
	
sl@0
    93
	iCodec = &aCodec;
sl@0
    94
sl@0
    95
	// Allocate data buffer
sl@0
    96
	iSourceBufferSize = iCodec->SourceBufferSize();
sl@0
    97
	iSoundDevBufferSize = iCodec->SinkBufferSize();
sl@0
    98
sl@0
    99
	if ((!iSourceBufferSize)||(!iSoundDevBufferSize))
sl@0
   100
		{
sl@0
   101
		err = KErrArgument; //codec plugin has not specified buffer size
sl@0
   102
		}
sl@0
   103
sl@0
   104
	if (err == KErrNone)
sl@0
   105
		{
sl@0
   106
#ifdef __USE_MMF_TRANSFERBUFFERS__
sl@0
   107
		TRAP(err,iSourceBuffer = CreateTransferBufferL(iSourceBufferSize, static_cast<CMMFTransferBuffer*>(iSourceBuffer)));
sl@0
   108
#endif
sl@0
   109
#ifdef __USE_MMF_PTRBUFFERS__
sl@0
   110
		TRAP(err,iSourceBuffer = CreatePtrBufferL(iSourceBufferSize));
sl@0
   111
#else
sl@0
   112
		TRAP(err,iSourceBuffer = CMMFDataBuffer::NewL(iSourceBufferSize));
sl@0
   113
#endif
sl@0
   114
		}
sl@0
   115
	
sl@0
   116
	if (err == KErrNone)
sl@0
   117
		{
sl@0
   118
		if (iCodec->IsNullCodec())
sl@0
   119
			{//use source buffer for sound device buffer	
sl@0
   120
			iSoundDeviceBuffer = NULL;
sl@0
   121
			}
sl@0
   122
		else
sl@0
   123
			{//codec needs separate source and sound device buffers
sl@0
   124
			TRAP(err,iSoundDeviceBuffer = CMMFDataBuffer::NewL(iSoundDevBufferSize));
sl@0
   125
			}
sl@0
   126
		}
sl@0
   127
	return err;
sl@0
   128
	}
sl@0
   129
sl@0
   130
TInt CToneDataPath::Start()
sl@0
   131
	{
sl@0
   132
	TInt startError = KErrNone;
sl@0
   133
sl@0
   134
	if (!iCodec) 
sl@0
   135
		{//check that a codec has been added
sl@0
   136
		startError = KErrNotReady;
sl@0
   137
		}
sl@0
   138
	if ((!iSoundDevice.Handle())&&(!startError))
sl@0
   139
    	{//check that the sound drivers can be opened
sl@0
   140
   		startError = iSoundDevice.Open();
sl@0
   141
		}
sl@0
   142
sl@0
   143
	if (iState == EPaused)
sl@0
   144
		{//we are paused so need to resume play
sl@0
   145
		if (!startError)
sl@0
   146
			{
sl@0
   147
#ifdef _SCW_DEBUG
sl@0
   148
			RDebug::Print(_L("CToneDataPath::Start-Resume"));
sl@0
   149
#endif
sl@0
   150
			iAudioPlayer->ResumePlaying();
sl@0
   151
			iState = EPlaying;
sl@0
   152
			}
sl@0
   153
		}
sl@0
   154
	else if (!startError)
sl@0
   155
		{
sl@0
   156
#ifdef _SCW_DEBUG
sl@0
   157
		RDebug::Print(_L("CToneDataPath::Start-Normal"));
sl@0
   158
#endif
sl@0
   159
		// get sample rate and channels from RMdaDevSound
sl@0
   160
		RMdaDevSound::TCurrentSoundFormatBuf format;
sl@0
   161
		iSoundDevice.GetPlayFormat(format);
sl@0
   162
		iSampleRate = format().iRate;
sl@0
   163
		iChannels = format().iChannels;
sl@0
   164
		
sl@0
   165
		iNoMoreSourceData = EFalse;
sl@0
   166
		iSourceBuffer->SetLastBuffer(EFalse);
sl@0
   167
		iState = EPlaying;
sl@0
   168
		iSoundDeviceErrorReceiver->Start();
sl@0
   169
		TRAP(startError,FillSourceBufferL()); //get initial buffer of audio data
sl@0
   170
		if (startError == KErrNone)
sl@0
   171
			{
sl@0
   172
			// Start the player objects
sl@0
   173
			iAudioPlayer->Start();
sl@0
   174
			}
sl@0
   175
		else
sl@0
   176
			{//failed to start up correctly go back to stopped state
sl@0
   177
			iState = EStopped;
sl@0
   178
			iSoundDeviceErrorReceiver->Stop();
sl@0
   179
			}
sl@0
   180
   		}
sl@0
   181
	return startError;
sl@0
   182
	}
sl@0
   183
sl@0
   184
sl@0
   185
// *** Main Play Loop ***
sl@0
   186
sl@0
   187
void CToneDataPath::FillSourceBufferL()
sl@0
   188
	{//asks observer to fill the source buffer          
sl@0
   189
    // Ask immediately for data from the observer
sl@0
   190
#ifdef __CYCLE_MMF_DATABUFFERS__
sl@0
   191
	// Create a new buffer to replicate INC021405 Play-EOF-Play on HwAccelerated solution Panics
sl@0
   192
	// If the creation fails, we carry on regardless as the original buffer will not have been 
sl@0
   193
	// destroyed. Must do this as alloc fail tests will not run.
sl@0
   194
	if(iSourceBuffer)
sl@0
   195
		{
sl@0
   196
		iSourceBuffer = CycleAudioBuffer(iSourceBuffer);
sl@0
   197
		}
sl@0
   198
#endif // __CYCLE_MMF_DATABUFFERS__	
sl@0
   199
	User::LeaveIfError(iHwDeviceObserver->FillThisHwBuffer(*iSourceBuffer));
sl@0
   200
	
sl@0
   201
	}
sl@0
   202
sl@0
   203
sl@0
   204
void CToneDataPath::BufferFilledL(CMMFDataBuffer& aBuffer)
sl@0
   205
	{//call back from observer to indicate buffer has been filled
sl@0
   206
	
sl@0
   207
	if (iState == EStopped)
sl@0
   208
		{
sl@0
   209
		User::Leave(KErrNotReady);//ok if paused?
sl@0
   210
		}
sl@0
   211
sl@0
   212
	iSourceBuffer = &aBuffer;
sl@0
   213
	iSourceBuffer->SetStatus(EFull);
sl@0
   214
#ifdef _SCW_DEBUG
sl@0
   215
	RDebug::Print(_L("CToneDataPath::BufferFilledL"));
sl@0
   216
#endif
sl@0
   217
sl@0
   218
	//need to check that the buffer size is not 0 - if so assume we've reached the end of the data
sl@0
   219
	iBuffSize = iSourceBuffer->BufferSize();
sl@0
   220
	if (!iBuffSize)
sl@0
   221
		{//no buffer  - could be end of source or could be that the source has no data??
sl@0
   222
		iNoMoreSourceData = ETrue;
sl@0
   223
#ifdef _SCW_DEBUG
sl@0
   224
		RDebug::Print(_L("CToneDataPath::BufferFilledL-NoMoreSourceData"));
sl@0
   225
#endif
sl@0
   226
		}
sl@0
   227
	//even if the buffer size is 0 we still 
sl@0
   228
	//need to perform the following to get the sound device callback
sl@0
   229
	FillSoundDeviceBufferL(); //get buffer in pcm16 format for sound device	
sl@0
   230
	
sl@0
   231
	iAudioPlayer->PlayData(*iSoundDeviceBuffer); //play data to sound drivers
sl@0
   232
	}
sl@0
   233
sl@0
   234
sl@0
   235
void CToneDataPath::FillSoundDeviceBufferL()
sl@0
   236
	{//use CToneCodec to fill the sound device buffer
sl@0
   237
	
sl@0
   238
	CToneCodec::TCodecProcessResult codecProcessResult;
sl@0
   239
sl@0
   240
	if (iCodec->IsNullCodec())
sl@0
   241
		{//no codec so data can be sent direct to sink
sl@0
   242
		iSoundDeviceBuffer = iSourceBuffer;
sl@0
   243
		iSoundDeviceBuffer->SetStatus(EFull);	//sink buffer is full
sl@0
   244
		}
sl@0
   245
	else 
sl@0
   246
		{
sl@0
   247
		//pass buffer to codec for processing
sl@0
   248
		codecProcessResult = iCodec->ProcessL(*iSourceBuffer, *iSoundDeviceBuffer);
sl@0
   249
		
sl@0
   250
		if (iSourceBuffer->LastBuffer()) //if source is last buffer so is sound dev
sl@0
   251
			{
sl@0
   252
			iSoundDeviceBuffer->SetLastBuffer(ETrue);
sl@0
   253
			}
sl@0
   254
		if ((!iSoundDeviceBuffer->BufferSize())&&(codecProcessResult.iDstBytesAdded))
sl@0
   255
			{//the codec has added data but not set the buffer length
sl@0
   256
			iSoundDeviceBuffer->Data().SetLength(codecProcessResult.iDstBytesAdded);
sl@0
   257
			}
sl@0
   258
		//only supports EProcessComplete
sl@0
   259
		switch (codecProcessResult.iCodecProcessStatus)
sl@0
   260
			{
sl@0
   261
		case CToneCodec::TCodecProcessResult::EProcessComplete:
sl@0
   262
		//finished procesing source data - all data in sink buffer
sl@0
   263
			{
sl@0
   264
			iSoundDeviceBuffer->SetStatus(EFull);	//sink buffer is full	
sl@0
   265
			}
sl@0
   266
		break;
sl@0
   267
#ifdef SYMBIAN_VARIABLE_BITRATE_CODEC
sl@0
   268
		case CToneCodec::TCodecProcessResult::EProcessIncomplete:
sl@0
   269
		//finished procesing source data - all data in sink buffer
sl@0
   270
			{
sl@0
   271
			iSoundDeviceBuffer->SetStatus(EFull);	//sink buffer is full	
sl@0
   272
			}
sl@0
   273
		break;
sl@0
   274
#endif
sl@0
   275
		case CToneCodec::TCodecProcessResult::EDstNotFilled:
sl@0
   276
		//could be the last buffer in which case dst might not get filled
sl@0
   277
			{
sl@0
   278
			iSoundDeviceBuffer->SetStatus(EFull);	//sink buffer is full	
sl@0
   279
			}
sl@0
   280
		break;
sl@0
   281
		case CToneCodec::TCodecProcessResult::EEndOfData:
sl@0
   282
			//no more data - send what we've got to the sink
sl@0
   283
			//note we can't always rely on this  - in many cases the codec will not know when
sl@0
   284
			//it has reached the end of data.
sl@0
   285
			{
sl@0
   286
			iSoundDeviceBuffer->SetStatus(EFull);//sink buffer may not really be 'full' but its as full as it going to get
sl@0
   287
			iNoMoreSourceData = ETrue;
sl@0
   288
			//doesn't matter if sink buffer is not full
sl@0
   289
			}
sl@0
   290
		break;
sl@0
   291
		default:
sl@0
   292
			//Panic(EMMFSwCodecWrapperBadCodec); //should never get here - bad codec
sl@0
   293
			break;
sl@0
   294
			}
sl@0
   295
		}
sl@0
   296
	}
sl@0
   297
sl@0
   298
sl@0
   299
void CToneDataPath::BufferEmptiedL(const CMMFDataBuffer& aBuffer)
sl@0
   300
	{//call back from CToneDataPathPlayer when the sound device buffer has been emptied
sl@0
   301
	if (&aBuffer != iSoundDeviceBuffer) 
sl@0
   302
		{
sl@0
   303
		Panic(EToneBadBuffer);
sl@0
   304
		}
sl@0
   305
sl@0
   306
	if (!iNoMoreSourceData) 
sl@0
   307
		{
sl@0
   308
		FillSourceBufferL();
sl@0
   309
		}
sl@0
   310
	}
sl@0
   311
sl@0
   312
//*** End of Main Play Loop ***
sl@0
   313
sl@0
   314
sl@0
   315
void CToneDataPath::Stop()
sl@0
   316
	{
sl@0
   317
	iAudioPlayer->Cancel();
sl@0
   318
	iSoundDeviceErrorReceiver->Cancel();
sl@0
   319
    iSoundDevice.Close();
sl@0
   320
sl@0
   321
#ifdef __CYCLE_MMF_DATABUFFERS__
sl@0
   322
	// Create a new buffer to replicate INC021405 Play-EOF-Play on HwAccelerated solution Panics
sl@0
   323
	// If the creation fails, we carry on regardless as the original buffer will not have been 
sl@0
   324
	// destroyed. Must do this as alloc fail tests will not run.
sl@0
   325
	if(iSourceBuffer)
sl@0
   326
		{
sl@0
   327
		iSourceBuffer = CycleAudioBuffer(iSourceBuffer);
sl@0
   328
		}
sl@0
   329
#endif // __CYCLE_MMF_DATABUFFERS__	
sl@0
   330
sl@0
   331
	iState = EStopped;
sl@0
   332
	}
sl@0
   333
sl@0
   334
sl@0
   335
void CToneDataPath::Pause()
sl@0
   336
	{
sl@0
   337
	//since a pause can happen anyway in the datatransfer -need to set to a known 
sl@0
   338
	//state so that when play is resumed the behaviour is predictable
sl@0
   339
	if (iSoundDevice.Handle())
sl@0
   340
		{
sl@0
   341
		iSoundDevice.PausePlayBuffer(); //needs new LDD
sl@0
   342
		iState = EPaused;
sl@0
   343
#ifdef _SCW_DEBUG
sl@0
   344
		RDebug::Print(_L("Pause"));
sl@0
   345
#endif
sl@0
   346
		}
sl@0
   347
	else
sl@0
   348
		{//an error must have occured 
sl@0
   349
		iState = EStopped;
sl@0
   350
		}
sl@0
   351
	}
sl@0
   352
	
sl@0
   353
	
sl@0
   354
TInt CToneDataPath::EmptyBuffers()
sl@0
   355
	{
sl@0
   356
	TInt error = KErrNone;
sl@0
   357
	if (iSoundDevice.Handle() == 0)
sl@0
   358
		{
sl@0
   359
		error = KErrNotReady;		
sl@0
   360
		}
sl@0
   361
	else
sl@0
   362
		{
sl@0
   363
		iSoundDevice.FlushPlayBuffer();
sl@0
   364
		}
sl@0
   365
	return error;
sl@0
   366
	}	
sl@0
   367
sl@0
   368
sl@0
   369
RMdaDevSound& CToneDataPath::Device()
sl@0
   370
	{
sl@0
   371
	return iSoundDevice;
sl@0
   372
	}
sl@0
   373
sl@0
   374
sl@0
   375
void CToneDataPath::SoundDeviceException(TInt aError)
sl@0
   376
	{
sl@0
   377
	if(iIgnoreUnderflow)
sl@0
   378
		{
sl@0
   379
		if((aError == KErrUnderflow) && (!iNoMoreSourceData))
sl@0
   380
			{
sl@0
   381
			//ignore underflow
sl@0
   382
			return;
sl@0
   383
			}
sl@0
   384
		}
sl@0
   385
sl@0
   386
	//this sends a request to the hw device observer
sl@0
   387
	//to update the bytes played
sl@0
   388
	//it is done here so that the sound driver can be closed prior to
sl@0
   389
	//updating the policy and sending the error back
sl@0
   390
	TUid uidUpdateBytesPlayed;
sl@0
   391
	uidUpdateBytesPlayed.iUid = KToneHwDeviceObserverUpdateBytesPlayed;
sl@0
   392
	TPtrC8 dummy(0,0);
sl@0
   393
	
sl@0
   394
	ASSERT(iHwDeviceObserver);
sl@0
   395
	iHwDeviceObserver->MsgFromHwDevice(uidUpdateBytesPlayed,dummy);
sl@0
   396
sl@0
   397
	//this closes RMdaDevSound.
sl@0
   398
	Stop(); 
sl@0
   399
sl@0
   400
	//inform devsound so it can update policy
sl@0
   401
	iHwDeviceObserver->Stopped(); 
sl@0
   402
sl@0
   403
	// Inform the observer of the exception condition
sl@0
   404
	// We inform the hw device observer after the policy has been
sl@0
   405
	// updated incase the observer relied on the error to assume
sl@0
   406
	// the policy has been updated
sl@0
   407
	iHwDeviceObserver->Error(aError);
sl@0
   408
	
sl@0
   409
	RDebug::Print(_L("CToneDataPath::iHwDeviceObserver->Error(%d)"),aError);
sl@0
   410
	}
sl@0
   411
sl@0
   412
/**
sl@0
   413
Retrieves a custom interface to the device.
sl@0
   414
The reference CToneDataPath supports three  custom interfaces,
sl@0
   415
MEmptyBuffersCustomInterface, MSetVbrFlagCustomInterface and MIgnoreUnderflowEventsCustomInterface
sl@0
   416
sl@0
   417
@param	aInterface
sl@0
   418
		Interface UID, defined with the custom interface.
sl@0
   419
		aInterface = KMmfUidEmptyBuffersCustomInterface for MEmptyBuffersCustomInterface,
sl@0
   420
					 KSetVbrFlagCustomInterfaceTypeUid for MSetVbrFlagCustomInterface
sl@0
   421
		
sl@0
   422
@return A pointer to the interface implementation, or NULL if the device can not
sl@0
   423
		implement the interface requested. The return value must be cast to the
sl@0
   424
		correct type by the user.
sl@0
   425
*/
sl@0
   426
TAny* CToneDataPath::CustomInterface(TUid aInterface)
sl@0
   427
	{
sl@0
   428
	TAny* ret = NULL;
sl@0
   429
sl@0
   430
	if (aInterface == KIgnoreUnderflowCustomInterfaceTypeUid)
sl@0
   431
		{
sl@0
   432
		MIgnoreUnderflowEventsCustomInterface* result = static_cast<MIgnoreUnderflowEventsCustomInterface*> (this);
sl@0
   433
		ret = static_cast<TAny*>(result);
sl@0
   434
		}
sl@0
   435
	return ret;
sl@0
   436
	}
sl@0
   437
sl@0
   438
sl@0
   439
void CToneDataPath::IgnoreUnderflowEvents()
sl@0
   440
	{
sl@0
   441
	iIgnoreUnderflow = ETrue;
sl@0
   442
	}
sl@0
   443
sl@0
   444
sl@0
   445
sl@0
   446
/************************************************************************
sl@0
   447
 *				CDataPathPlayer											*
sl@0
   448
 ************************************************************************/
sl@0
   449
sl@0
   450
CToneDataPathPlayer::CToneDataPathPlayer(CToneDataPath& aParent, TInt aPriority)
sl@0
   451
: CActive(aPriority), iParent(aParent)
sl@0
   452
	{
sl@0
   453
	CActiveScheduler::Add(this);
sl@0
   454
	}
sl@0
   455
sl@0
   456
sl@0
   457
CToneDataPathPlayer::~CToneDataPathPlayer()
sl@0
   458
	{
sl@0
   459
	Cancel();
sl@0
   460
	}
sl@0
   461
sl@0
   462
sl@0
   463
void CToneDataPathPlayer::Start()
sl@0
   464
	{
sl@0
   465
	// No implementation
sl@0
   466
	}
sl@0
   467
sl@0
   468
sl@0
   469
void CToneDataPathPlayer::ResumePlaying()
sl@0
   470
	{
sl@0
   471
	if (iParent.Device().Handle())
sl@0
   472
		{
sl@0
   473
		//should be ok to call this even if we are active
sl@0
   474
		iParent.Device().ResumePlaying(); 
sl@0
   475
		iResumePlaying = ETrue;
sl@0
   476
		}
sl@0
   477
#ifdef _SCW_DEBUG
sl@0
   478
	RDebug::Print(_L("Playing Resumed"));
sl@0
   479
#endif
sl@0
   480
	}
sl@0
   481
sl@0
   482
sl@0
   483
void CToneDataPathPlayer::PlayData(const CMMFDataBuffer& aData)
sl@0
   484
	{
sl@0
   485
	iDataFromSource = &aData;
sl@0
   486
	if (!IsActive())
sl@0
   487
		{
sl@0
   488
#ifdef _SCW_DEBUG
sl@0
   489
		RDebug::Print(_L("CToneDataPathPlayer::PlayData"));
sl@0
   490
#endif
sl@0
   491
		iParent.Device().PlayData(iStatus,(static_cast<const CMMFDataBuffer*> (iDataFromSource))->Data());
sl@0
   492
		SetActive();
sl@0
   493
		}
sl@0
   494
	}
sl@0
   495
sl@0
   496
sl@0
   497
void CToneDataPathPlayer::Stop()
sl@0
   498
	{
sl@0
   499
	if (!IsActive())
sl@0
   500
		{
sl@0
   501
		iParent.Device().FlushPlayBuffer(); // Otherwise won't be flushed
sl@0
   502
		}
sl@0
   503
	Cancel();
sl@0
   504
	iParent.SoundDeviceException(KErrCancel);
sl@0
   505
	}
sl@0
   506
sl@0
   507
sl@0
   508
void CToneDataPathPlayer::RunL()
sl@0
   509
	{
sl@0
   510
#ifdef _SCW_DEBUG
sl@0
   511
	RDebug::Print(_L("CToneDataPathPlayer::RunL error[%d]"), iStatus.Int());
sl@0
   512
#endif
sl@0
   513
	if (iStatus.Int()!=KErrNone)
sl@0
   514
		{
sl@0
   515
		iParent.SoundDeviceException(iStatus.Int());
sl@0
   516
		}
sl@0
   517
	else
sl@0
   518
		{
sl@0
   519
		iParent.BufferEmptiedL(static_cast<const CMMFDataBuffer&>(*iDataFromSource));
sl@0
   520
		iResumePlaying = EFalse;
sl@0
   521
		}
sl@0
   522
	}
sl@0
   523
sl@0
   524
sl@0
   525
TInt CToneDataPathPlayer::RunError(TInt aError)
sl@0
   526
	{
sl@0
   527
	Error(aError);
sl@0
   528
	return KErrNone;
sl@0
   529
	}
sl@0
   530
sl@0
   531
sl@0
   532
void CToneDataPathPlayer::DoCancel()
sl@0
   533
	{
sl@0
   534
	if (iParent.Device().Handle())
sl@0
   535
		{
sl@0
   536
		iParent.Device().CancelPlayData();
sl@0
   537
		iParent.Device().FlushPlayBuffer();
sl@0
   538
		}
sl@0
   539
	}
sl@0
   540
sl@0
   541
sl@0
   542
void CToneDataPathPlayer::Error(TInt aError)
sl@0
   543
	{ 
sl@0
   544
	iParent.SoundDeviceException(aError);
sl@0
   545
	}
sl@0
   546
sl@0
   547
sl@0
   548
sl@0
   549
/************************************************************************
sl@0
   550
 *				CToneSoundDevPlayErrorReceiver							*
sl@0
   551
 ************************************************************************/
sl@0
   552
sl@0
   553
CToneSoundDevPlayErrorReceiver::CToneSoundDevPlayErrorReceiver(CToneDataPath& aParent, TInt aPriority)
sl@0
   554
: CActive(aPriority), iParent(aParent)
sl@0
   555
	{
sl@0
   556
	CActiveScheduler::Add(this);
sl@0
   557
	}
sl@0
   558
sl@0
   559
CToneSoundDevPlayErrorReceiver::~CToneSoundDevPlayErrorReceiver()
sl@0
   560
	{
sl@0
   561
	Cancel();
sl@0
   562
	}
sl@0
   563
sl@0
   564
void CToneSoundDevPlayErrorReceiver::Start()
sl@0
   565
	{
sl@0
   566
	iParent.Device().NotifyPlayError(iStatus);
sl@0
   567
	SetActive();
sl@0
   568
	}
sl@0
   569
sl@0
   570
void CToneSoundDevPlayErrorReceiver::Stop()
sl@0
   571
	{
sl@0
   572
	Cancel();
sl@0
   573
	}
sl@0
   574
sl@0
   575
void CToneSoundDevPlayErrorReceiver::RunL()
sl@0
   576
	{
sl@0
   577
	TInt reason = iStatus.Int();
sl@0
   578
	Start();
sl@0
   579
sl@0
   580
	// An error has been returned
sl@0
   581
#ifdef _SCW_DEBUG
sl@0
   582
	RDebug::Print(_L("CToneSoundDevPlayErrorReceiver::RunL[%d]"), reason);
sl@0
   583
#endif
sl@0
   584
	iParent.SoundDeviceException(reason);
sl@0
   585
	}
sl@0
   586
sl@0
   587
void CToneSoundDevPlayErrorReceiver::DoCancel()
sl@0
   588
	{
sl@0
   589
	iParent.Device().CancelNotifyPlayError();
sl@0
   590
	}
sl@0
   591
sl@0
   592
sl@0
   593
sl@0
   594
/*
sl@0
   595
 * CycleAudioBufferL
sl@0
   596
 *
sl@0
   597
 * Sets up a usable buffer for passing to MMF
sl@0
   598
 *	
sl@0
   599
 * This method has been written such that it must allocate a new buffer before
sl@0
   600
 * replacing the existing one. The purpose of this is to force creation of a 
sl@0
   601
 * new buffer. Simply deleting and then re-allocing may result in the same 
sl@0
   602
 * address being used.
sl@0
   603
 * 
sl@0
   604
 * Only cycles if there is enough memory
sl@0
   605
 *
sl@0
   606
 */
sl@0
   607
#ifdef __CYCLE_MMF_DATABUFFERS__
sl@0
   608
CMMFDataBuffer* CToneDataPath::CycleAudioBuffer(CMMFDataBuffer* aBuffer)
sl@0
   609
	{
sl@0
   610
	CMMFDataBuffer* buffer = NULL;
sl@0
   611
	TUint bufferSize = aBuffer->Data().MaxLength();
sl@0
   612
sl@0
   613
#ifdef __USE_MMF_TRANSFERBUFFERS__
sl@0
   614
	TRAPD(err, buffer = CreateTransferBufferL(bufferSize, static_cast<CMMFTransferBuffer*>(aBuffer)));
sl@0
   615
#else
sl@0
   616
	TRAPD(err,buffer = CMMFDataBuffer::NewL(bufferSize));
sl@0
   617
sl@0
   618
	if (err == KErrNone)
sl@0
   619
		{
sl@0
   620
		delete aBuffer;
sl@0
   621
		}
sl@0
   622
#endif
sl@0
   623
	if (err != KErrNone)
sl@0
   624
		{//there was a problem creating buffer eg OOM so use same buffer
sl@0
   625
		buffer = aBuffer;
sl@0
   626
		}
sl@0
   627
sl@0
   628
	return buffer;
sl@0
   629
sl@0
   630
	}
sl@0
   631
#endif
sl@0
   632
sl@0
   633
/*
sl@0
   634
 * DoCleanupRHandleBase
sl@0
   635
 *
sl@0
   636
 * This method will initially Close the handle and then delete it.
sl@0
   637
 *
sl@0
   638
 */
sl@0
   639
#ifdef __USE_MMF_TRANSFERBUFFERS__
sl@0
   640
inline static void DoCleanupRHandleBase(TAny* aRHandleBase)
sl@0
   641
	{
sl@0
   642
	ASSERT(aRHandleBase);
sl@0
   643
	RHandleBase* rHandleBase = static_cast<RHandleBase*> (aRHandleBase);
sl@0
   644
	TRAPD(error, rHandleBase->Close());
sl@0
   645
	delete aRHandleBase;
sl@0
   646
	}
sl@0
   647
sl@0
   648
CMMFTransferBuffer* CToneDataPath::CreateTransferBufferL(TUint aBufferSize, CMMFTransferBuffer* aOldBuffer)
sl@0
   649
	{
sl@0
   650
	CMMFTransferBuffer* buffer = NULL;
sl@0
   651
sl@0
   652
	RTransferBuffer* transBuffer = new  (ELeave) RTransferBuffer;
sl@0
   653
	
sl@0
   654
	TCleanupItem bufferCleanupItem(DoCleanupRHandleBase, transBuffer); //closes and deletes.
sl@0
   655
	CleanupStack::PushL(bufferCleanupItem);
sl@0
   656
sl@0
   657
	RTransferWindow* transWindow = new (ELeave) RTransferWindow;
sl@0
   658
	
sl@0
   659
	TCleanupItem windowCleanupItem(DoCleanupRHandleBase, transWindow); //closes and deletes.
sl@0
   660
	CleanupStack::PushL(windowCleanupItem);
sl@0
   661
sl@0
   662
	User::LeaveIfError(transBuffer->Create(aBufferSize));
sl@0
   663
	User::LeaveIfError(transWindow->Create(aBufferSize));
sl@0
   664
	User::LeaveIfError(transWindow->MapInBuffer(*transBuffer));
sl@0
   665
sl@0
   666
	buffer = CMMFTransferBuffer::NewL(*transWindow);
sl@0
   667
sl@0
   668
	delete aOldBuffer; //closes RTransferWindow
sl@0
   669
	delete iTransferWindow;
sl@0
   670
sl@0
   671
	if(iTransferBuffer)
sl@0
   672
		{
sl@0
   673
		iTransferBuffer->Close();
sl@0
   674
		}
sl@0
   675
	delete iTransferBuffer;
sl@0
   676
sl@0
   677
	iTransferBuffer = transBuffer;
sl@0
   678
	iTransferWindow = transWindow;
sl@0
   679
sl@0
   680
	CleanupStack::Pop(transWindow); 
sl@0
   681
	CleanupStack::Pop(transBuffer); 
sl@0
   682
sl@0
   683
	return buffer;
sl@0
   684
	}
sl@0
   685
#endif
sl@0
   686
sl@0
   687
sl@0
   688
#ifdef __USE_MMF_PTRBUFFERS__
sl@0
   689
CMMFPtrBuffer* CToneDataPath::CreatePtrBufferL(TUint aBufferSize)
sl@0
   690
	{
sl@0
   691
	CMMFPtrBuffer* buffer = NULL;
sl@0
   692
	if (iPtrBufferMemoryBlock)
sl@0
   693
		{
sl@0
   694
		delete iPtrBufferMemoryBlock;//incase already exisits
sl@0
   695
		}
sl@0
   696
	iPtrBufferMemoryBlock = HBufC8::NewL(aBufferSize);
sl@0
   697
	TPtr8 ptrMemoryBlock(iPtrBufferMemoryBlock->Des());
sl@0
   698
	buffer = CMMFPtrBuffer::NewL(ptrMemoryBlock);
sl@0
   699
	return buffer;
sl@0
   700
	}
sl@0
   701
#endif  // __USE_MMF_PTRBUFFERS__
sl@0
   702
sl@0
   703
sl@0
   704