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