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 |
// source\server\MmfBtSwCodecPlayDatapath.cpp
|
sl@0
|
15 |
//
|
sl@0
|
16 |
//
|
sl@0
|
17 |
|
sl@0
|
18 |
#include "mmfBtSwCodecPlayDataPath.h"
|
sl@0
|
19 |
#include "mmfbtswcodecwrapper.h"
|
sl@0
|
20 |
#include "mmfbtswcodecwrappercustominterfacesuids.hrh"
|
sl@0
|
21 |
#include <mmfpaniccodes.h>
|
sl@0
|
22 |
#include "mmfBtSwCodecUtility.h"
|
sl@0
|
23 |
|
sl@0
|
24 |
#include "MMFBtRoutingSoundDevice.h"
|
sl@0
|
25 |
#include "A2dpBTHeadsetAudioIfClientServer.h" // for TRange (will be deprecated)
|
sl@0
|
26 |
|
sl@0
|
27 |
CMMFSwCodecPlayDataPath* CMMFSwCodecPlayDataPath::NewL( CRoutingSoundPlayDevice* aSoundDevice,
|
sl@0
|
28 |
TUid aDeviceUid)
|
sl@0
|
29 |
{
|
sl@0
|
30 |
CMMFSwCodecPlayDataPath* self = new(ELeave) CMMFSwCodecPlayDataPath(aSoundDevice,
|
sl@0
|
31 |
aDeviceUid);
|
sl@0
|
32 |
CleanupStack::PushL(self);
|
sl@0
|
33 |
self->ConstructL();
|
sl@0
|
34 |
CleanupStack::Pop();
|
sl@0
|
35 |
return self;
|
sl@0
|
36 |
}
|
sl@0
|
37 |
|
sl@0
|
38 |
|
sl@0
|
39 |
void CMMFSwCodecPlayDataPath::ConstructL()
|
sl@0
|
40 |
{
|
sl@0
|
41 |
iAudioPlayer = new (ELeave) CDataPathPlayer(*this,CActive::EPriorityUserInput);
|
sl@0
|
42 |
iSoundDeviceErrorReceiver = new (ELeave) CSoundDevPlayErrorReceiver(*this, CActive::EPriorityUserInput);
|
sl@0
|
43 |
iUtility = CMMFSwCodecUtility::NewL();
|
sl@0
|
44 |
}
|
sl@0
|
45 |
|
sl@0
|
46 |
|
sl@0
|
47 |
CMMFSwCodecPlayDataPath::~CMMFSwCodecPlayDataPath()
|
sl@0
|
48 |
{
|
sl@0
|
49 |
delete iAudioPlayer;
|
sl@0
|
50 |
delete iSoundDeviceErrorReceiver;
|
sl@0
|
51 |
delete iUtility;
|
sl@0
|
52 |
|
sl@0
|
53 |
TRequestStatus status;
|
sl@0
|
54 |
iSoundDevice->CloseDevice(iDeviceUid, status);
|
sl@0
|
55 |
//TODO there should be a timeout for the line below
|
sl@0
|
56 |
User::WaitForRequest(status);
|
sl@0
|
57 |
|
sl@0
|
58 |
if (iCodec)
|
sl@0
|
59 |
{
|
sl@0
|
60 |
delete iSourceBuffer;
|
sl@0
|
61 |
if (!iCodec->IsNullCodec())
|
sl@0
|
62 |
{
|
sl@0
|
63 |
delete iSoundDeviceBuffer;
|
sl@0
|
64 |
}
|
sl@0
|
65 |
}
|
sl@0
|
66 |
|
sl@0
|
67 |
#ifdef __USE_MMF_TRANSFERBUFFERS__
|
sl@0
|
68 |
delete iTransferWindow;
|
sl@0
|
69 |
|
sl@0
|
70 |
if(iTransferBuffer)
|
sl@0
|
71 |
{
|
sl@0
|
72 |
iTransferBuffer->Close();
|
sl@0
|
73 |
delete iTransferBuffer;
|
sl@0
|
74 |
}
|
sl@0
|
75 |
#endif
|
sl@0
|
76 |
|
sl@0
|
77 |
#ifdef __USE_MMF_PTRBUFFERS__
|
sl@0
|
78 |
delete iPtrBufferMemoryBlock;
|
sl@0
|
79 |
#endif
|
sl@0
|
80 |
}
|
sl@0
|
81 |
|
sl@0
|
82 |
|
sl@0
|
83 |
TInt CMMFSwCodecPlayDataPath::SetObserver(MMMFHwDeviceObserver& aObserver)
|
sl@0
|
84 |
{
|
sl@0
|
85 |
TInt error;
|
sl@0
|
86 |
if (iHwDeviceObserver)
|
sl@0
|
87 |
{
|
sl@0
|
88 |
error = KErrAlreadyExists;
|
sl@0
|
89 |
}
|
sl@0
|
90 |
else
|
sl@0
|
91 |
{
|
sl@0
|
92 |
iHwDeviceObserver = &aObserver;
|
sl@0
|
93 |
error = KErrNone;
|
sl@0
|
94 |
}
|
sl@0
|
95 |
return error;
|
sl@0
|
96 |
}
|
sl@0
|
97 |
|
sl@0
|
98 |
|
sl@0
|
99 |
TInt CMMFSwCodecPlayDataPath::AddCodec(CMMFSwCodec& aCodec)
|
sl@0
|
100 |
{
|
sl@0
|
101 |
if (iCodec)
|
sl@0
|
102 |
{
|
sl@0
|
103 |
return KErrNotSupported; //doesn't support multiple codecs
|
sl@0
|
104 |
}
|
sl@0
|
105 |
|
sl@0
|
106 |
TInt err = KErrNone;
|
sl@0
|
107 |
|
sl@0
|
108 |
iCodec = &aCodec;
|
sl@0
|
109 |
|
sl@0
|
110 |
// Allocate data buffer
|
sl@0
|
111 |
iSourceBufferSize = iCodec->SourceBufferSize();
|
sl@0
|
112 |
iSoundDevBufferSize = iCodec->SinkBufferSize();
|
sl@0
|
113 |
|
sl@0
|
114 |
if ((!iSourceBufferSize) || (!iSoundDevBufferSize))
|
sl@0
|
115 |
{
|
sl@0
|
116 |
err = KErrArgument; //codec plugin has not specified buffer size
|
sl@0
|
117 |
}
|
sl@0
|
118 |
|
sl@0
|
119 |
if (err == KErrNone)
|
sl@0
|
120 |
{
|
sl@0
|
121 |
#ifdef __USE_MMF_TRANSFERBUFFERS__
|
sl@0
|
122 |
TRAP(err,iSourceBuffer = CreateTransferBufferL(iSourceBufferSize, static_cast<CMMFTransferBuffer*>(iSourceBuffer)));
|
sl@0
|
123 |
#endif
|
sl@0
|
124 |
#ifdef __USE_MMF_PTRBUFFERS__
|
sl@0
|
125 |
TRAP(err,iSourceBuffer = CreatePtrBufferL(iSourceBufferSize));
|
sl@0
|
126 |
#else
|
sl@0
|
127 |
TRAP(err,iSourceBuffer = CMMFDataBuffer::NewL(iSourceBufferSize));
|
sl@0
|
128 |
#endif
|
sl@0
|
129 |
}
|
sl@0
|
130 |
|
sl@0
|
131 |
if (err == KErrNone)
|
sl@0
|
132 |
{
|
sl@0
|
133 |
if (iCodec->IsNullCodec())
|
sl@0
|
134 |
{//use source buffer for sound device buffer
|
sl@0
|
135 |
iSoundDeviceBuffer = NULL;
|
sl@0
|
136 |
}
|
sl@0
|
137 |
else
|
sl@0
|
138 |
{//codec needs separate source and sound device buffers
|
sl@0
|
139 |
TRAP(err,iSoundDeviceBuffer = CMMFDataBuffer::NewL(iSoundDevBufferSize));
|
sl@0
|
140 |
}
|
sl@0
|
141 |
}
|
sl@0
|
142 |
return err;
|
sl@0
|
143 |
}
|
sl@0
|
144 |
|
sl@0
|
145 |
|
sl@0
|
146 |
TInt CMMFSwCodecPlayDataPath::Start()
|
sl@0
|
147 |
{
|
sl@0
|
148 |
TInt startError = KErrNone;
|
sl@0
|
149 |
|
sl@0
|
150 |
if (!iCodec || (!iSoundDevice->Handle()))
|
sl@0
|
151 |
{
|
sl@0
|
152 |
//check that a codec has been added and the sound device is open
|
sl@0
|
153 |
startError = KErrNotReady;
|
sl@0
|
154 |
}
|
sl@0
|
155 |
|
sl@0
|
156 |
if (iState == EPaused)
|
sl@0
|
157 |
{//we are paused so need to resume play
|
sl@0
|
158 |
if (!startError)
|
sl@0
|
159 |
{
|
sl@0
|
160 |
#ifdef _SCW_DEBUG
|
sl@0
|
161 |
RDebug::Print(_L("CMMFSwCodecPlayDataPath::Start-Resume"));
|
sl@0
|
162 |
#endif
|
sl@0
|
163 |
iAudioPlayer->ResumePlaying();
|
sl@0
|
164 |
iState = EPlaying;
|
sl@0
|
165 |
}
|
sl@0
|
166 |
}
|
sl@0
|
167 |
else if (!startError)
|
sl@0
|
168 |
{
|
sl@0
|
169 |
#ifdef _SCW_DEBUG
|
sl@0
|
170 |
RDebug::Print(_L("CMMFSwCodecPlayDataPath::Start-Normal"));
|
sl@0
|
171 |
#endif
|
sl@0
|
172 |
if (!startError)
|
sl@0
|
173 |
{
|
sl@0
|
174 |
iNoMoreSourceData = EFalse;
|
sl@0
|
175 |
iSourceBuffer->SetLastBuffer(EFalse);
|
sl@0
|
176 |
iState = EPlaying;
|
sl@0
|
177 |
iSoundDeviceErrorReceiver->Start();
|
sl@0
|
178 |
TRAP(startError, FillSourceBufferL()); //get initial buffer of audio data
|
sl@0
|
179 |
if (startError == KErrNone)
|
sl@0
|
180 |
{
|
sl@0
|
181 |
// Start the player objects
|
sl@0
|
182 |
iAudioPlayer->Start();
|
sl@0
|
183 |
}
|
sl@0
|
184 |
else
|
sl@0
|
185 |
{//failed to start up correctly go back to stopped state
|
sl@0
|
186 |
iState = EStopped;
|
sl@0
|
187 |
iSoundDeviceErrorReceiver->Stop();
|
sl@0
|
188 |
}
|
sl@0
|
189 |
}
|
sl@0
|
190 |
}
|
sl@0
|
191 |
return startError;
|
sl@0
|
192 |
}
|
sl@0
|
193 |
|
sl@0
|
194 |
|
sl@0
|
195 |
// *** Main Play Loop ***
|
sl@0
|
196 |
|
sl@0
|
197 |
void CMMFSwCodecPlayDataPath::FillSourceBufferL()
|
sl@0
|
198 |
{//asks observer to fill the source buffer
|
sl@0
|
199 |
// Ask immediately for data from the observer
|
sl@0
|
200 |
#ifdef __CYCLE_MMF_DATABUFFERS__
|
sl@0
|
201 |
// Create a new buffer to replicate INC021405 Play-EOF-Play on HwAccelerated solution Panics
|
sl@0
|
202 |
// If the creation fails, we carry on regardless as the original buffer will not have been
|
sl@0
|
203 |
// destroyed. Must do this as alloc fail tests will not run.
|
sl@0
|
204 |
if(iSourceBuffer)
|
sl@0
|
205 |
{
|
sl@0
|
206 |
iSourceBuffer = CycleAudioBuffer(iSourceBuffer);
|
sl@0
|
207 |
}
|
sl@0
|
208 |
#endif // __CYCLE_MMF_DATABUFFERS__
|
sl@0
|
209 |
User::LeaveIfError(iHwDeviceObserver->FillThisHwBuffer(*iSourceBuffer));
|
sl@0
|
210 |
|
sl@0
|
211 |
}
|
sl@0
|
212 |
|
sl@0
|
213 |
|
sl@0
|
214 |
void CMMFSwCodecPlayDataPath::BufferFilledL(CMMFDataBuffer& aBuffer)
|
sl@0
|
215 |
{//call back from observer to indicate buffer has been filled
|
sl@0
|
216 |
if (iState == EStopped)
|
sl@0
|
217 |
User::Leave(KErrNotReady);//ok if paused?
|
sl@0
|
218 |
|
sl@0
|
219 |
iSourceBuffer = &aBuffer;
|
sl@0
|
220 |
iSourceBuffer->SetStatus(EFull);
|
sl@0
|
221 |
#ifdef _SCW_DEBUG
|
sl@0
|
222 |
RDebug::Print(_L("CMMFSwCodecPlayDataPath::BufferFilledL"));
|
sl@0
|
223 |
#endif
|
sl@0
|
224 |
|
sl@0
|
225 |
//need to check that the buffer size is not 0 - if so assume we've reached the end of the data
|
sl@0
|
226 |
if (!iSourceBuffer->BufferSize())
|
sl@0
|
227 |
{//no buffer - could be end of source or could be that the source has no data??
|
sl@0
|
228 |
iNoMoreSourceData = ETrue;
|
sl@0
|
229 |
#ifdef _SCW_DEBUG
|
sl@0
|
230 |
RDebug::Print(_L("CMMFSwCodecPlayDataPath::BufferFilledL-NoMoreSourceData"));
|
sl@0
|
231 |
#endif
|
sl@0
|
232 |
}
|
sl@0
|
233 |
//even if the buffer size is 0 we still
|
sl@0
|
234 |
//need to perform the following to get the sound device callback
|
sl@0
|
235 |
FillSoundDeviceBufferL(); //get buffer in pcm16 format for sound device
|
sl@0
|
236 |
|
sl@0
|
237 |
// attenuate the amplitude of the samples if volume ramping has been changed
|
sl@0
|
238 |
// and is non-zero
|
sl@0
|
239 |
if (iCustomInterface)
|
sl@0
|
240 |
{
|
sl@0
|
241 |
TTimeIntervalMicroSeconds volumeRamp = iCustomInterface->VolumeRamp();
|
sl@0
|
242 |
if (volumeRamp != iVolumeRamp)
|
sl@0
|
243 |
{
|
sl@0
|
244 |
iVolumeRamp = volumeRamp;
|
sl@0
|
245 |
if (iVolumeRamp.Int64() != 0)
|
sl@0
|
246 |
{
|
sl@0
|
247 |
iUtility->ConfigAudioRamper(
|
sl@0
|
248 |
iVolumeRamp.Int64(),
|
sl@0
|
249 |
iSampleRate,
|
sl@0
|
250 |
iChannels);
|
sl@0
|
251 |
iRampAudioSample = ETrue;
|
sl@0
|
252 |
}
|
sl@0
|
253 |
else
|
sl@0
|
254 |
{
|
sl@0
|
255 |
iRampAudioSample = EFalse;
|
sl@0
|
256 |
}
|
sl@0
|
257 |
}
|
sl@0
|
258 |
if (iRampAudioSample)
|
sl@0
|
259 |
{
|
sl@0
|
260 |
iRampAudioSample = iUtility->RampAudio(iSoundDeviceBuffer);
|
sl@0
|
261 |
}
|
sl@0
|
262 |
}
|
sl@0
|
263 |
|
sl@0
|
264 |
iAudioPlayer->PlayData(*iSoundDeviceBuffer); //play data to sound drivers
|
sl@0
|
265 |
|
sl@0
|
266 |
if (iSourceBuffer->LastBuffer())//check last buffer flag
|
sl@0
|
267 |
{
|
sl@0
|
268 |
iNoMoreSourceData = ETrue;
|
sl@0
|
269 |
#ifdef _SCW_DEBUG
|
sl@0
|
270 |
RDebug::Print(_L("CMMFSwCodecPlayDataPath::BufferFilledL-LBNoMoreSourceData"));
|
sl@0
|
271 |
#endif
|
sl@0
|
272 |
}
|
sl@0
|
273 |
}
|
sl@0
|
274 |
|
sl@0
|
275 |
|
sl@0
|
276 |
void CMMFSwCodecPlayDataPath::FillSoundDeviceBufferL()
|
sl@0
|
277 |
{//use CMMFSwCodec to fill the sound device buffer
|
sl@0
|
278 |
|
sl@0
|
279 |
CMMFSwCodec::TCodecProcessResult codecProcessResult;
|
sl@0
|
280 |
|
sl@0
|
281 |
if (iCodec->IsNullCodec())
|
sl@0
|
282 |
{//no codec so data can be sent direct to sink
|
sl@0
|
283 |
iSoundDeviceBuffer = iSourceBuffer;
|
sl@0
|
284 |
iSoundDeviceBuffer->SetStatus(EFull); //sink buffer is full
|
sl@0
|
285 |
}
|
sl@0
|
286 |
else
|
sl@0
|
287 |
{
|
sl@0
|
288 |
//pass buffer to codec for processing
|
sl@0
|
289 |
codecProcessResult = iCodec->ProcessL(*iSourceBuffer, *iSoundDeviceBuffer);
|
sl@0
|
290 |
if (iSourceBuffer->LastBuffer()) //if source is last buffer so is sound dev
|
sl@0
|
291 |
iSoundDeviceBuffer->SetLastBuffer(ETrue);
|
sl@0
|
292 |
if ((!iSoundDeviceBuffer->BufferSize())&&(codecProcessResult.iDstBytesAdded))
|
sl@0
|
293 |
{//the codec has added data but not set the buffer length
|
sl@0
|
294 |
iSoundDeviceBuffer->Data().SetLength(codecProcessResult.iDstBytesAdded);
|
sl@0
|
295 |
}
|
sl@0
|
296 |
//only supports EProcessComplete
|
sl@0
|
297 |
switch (codecProcessResult.iCodecProcessStatus)
|
sl@0
|
298 |
{
|
sl@0
|
299 |
case CMMFSwCodec::TCodecProcessResult::EProcessComplete:
|
sl@0
|
300 |
//finished procesing source data - all data in sink buffer
|
sl@0
|
301 |
{
|
sl@0
|
302 |
iSoundDeviceBuffer->SetStatus(EFull); //sink buffer is full
|
sl@0
|
303 |
}
|
sl@0
|
304 |
break;
|
sl@0
|
305 |
case CMMFSwCodec::TCodecProcessResult::EDstNotFilled:
|
sl@0
|
306 |
//could be the last buffer in which case dst might not get filled
|
sl@0
|
307 |
{
|
sl@0
|
308 |
iSoundDeviceBuffer->SetStatus(EFull); //sink buffer is full
|
sl@0
|
309 |
}
|
sl@0
|
310 |
break;
|
sl@0
|
311 |
case CMMFSwCodec::TCodecProcessResult::EEndOfData:
|
sl@0
|
312 |
//no more data - send what we've got to the sink
|
sl@0
|
313 |
//note we can't always rely on this - in many cases the codec will not know when
|
sl@0
|
314 |
//it has reached the end of data.
|
sl@0
|
315 |
{
|
sl@0
|
316 |
iSoundDeviceBuffer->SetStatus(EFull);//sink buffer may not really be 'full' but its as full as it going to get
|
sl@0
|
317 |
iNoMoreSourceData = ETrue;
|
sl@0
|
318 |
//doesn't matter if sink buffer is not full
|
sl@0
|
319 |
}
|
sl@0
|
320 |
break;
|
sl@0
|
321 |
default:
|
sl@0
|
322 |
Panic(EMMFSwCodecWrapperBadCodec); //should never get here - bad codec
|
sl@0
|
323 |
}
|
sl@0
|
324 |
}
|
sl@0
|
325 |
}
|
sl@0
|
326 |
|
sl@0
|
327 |
|
sl@0
|
328 |
void CMMFSwCodecPlayDataPath::BufferEmptiedL(const CMMFDataBuffer& aBuffer)
|
sl@0
|
329 |
{//call back from CDataPathPlayer when the sound device buffer has been emptied
|
sl@0
|
330 |
if (&aBuffer != iSoundDeviceBuffer)
|
sl@0
|
331 |
Panic(EMMFSwCodecWrapperBadBuffer);
|
sl@0
|
332 |
if (!iNoMoreSourceData)
|
sl@0
|
333 |
FillSourceBufferL();
|
sl@0
|
334 |
}
|
sl@0
|
335 |
|
sl@0
|
336 |
//*** End of Main Play Loop ***
|
sl@0
|
337 |
|
sl@0
|
338 |
|
sl@0
|
339 |
void CMMFSwCodecPlayDataPath::Stop()
|
sl@0
|
340 |
{
|
sl@0
|
341 |
iAudioPlayer->Cancel();
|
sl@0
|
342 |
iSoundDeviceErrorReceiver->Cancel();
|
sl@0
|
343 |
TRequestStatus status;
|
sl@0
|
344 |
iSoundDevice->CloseDevice(iDeviceUid, status);
|
sl@0
|
345 |
User::WaitForRequest(status);
|
sl@0
|
346 |
|
sl@0
|
347 |
#ifdef __CYCLE_MMF_DATABUFFERS__
|
sl@0
|
348 |
// Create a new buffer to replicate INC021405 Play-EOF-Play on HwAccelerated solution Panics
|
sl@0
|
349 |
// If the creation fails, we carry on regardless as the original buffer will not have been
|
sl@0
|
350 |
// destroyed. Must do this as alloc fail tests will not run.
|
sl@0
|
351 |
if(iSourceBuffer)
|
sl@0
|
352 |
{
|
sl@0
|
353 |
iSourceBuffer = CycleAudioBuffer(iSourceBuffer);
|
sl@0
|
354 |
}
|
sl@0
|
355 |
#endif // __CYCLE_MMF_DATABUFFERS__
|
sl@0
|
356 |
|
sl@0
|
357 |
iState = EStopped;
|
sl@0
|
358 |
}
|
sl@0
|
359 |
|
sl@0
|
360 |
|
sl@0
|
361 |
void CMMFSwCodecPlayDataPath::Pause()
|
sl@0
|
362 |
{
|
sl@0
|
363 |
//since a pause can happen anyway in the datatransfer -need to set to a known
|
sl@0
|
364 |
//state so that when play is resumed the behaviour is predictable
|
sl@0
|
365 |
if (iSoundDevice->Handle())
|
sl@0
|
366 |
{
|
sl@0
|
367 |
iSoundDevice->PauseBuffer(); // ignores return value?
|
sl@0
|
368 |
iState = EPaused;
|
sl@0
|
369 |
#ifdef _SCW_DEBUG
|
sl@0
|
370 |
RDebug::Print(_L("Pause"));
|
sl@0
|
371 |
#endif
|
sl@0
|
372 |
}
|
sl@0
|
373 |
else
|
sl@0
|
374 |
{//an error must have occured
|
sl@0
|
375 |
iState = EStopped;
|
sl@0
|
376 |
}
|
sl@0
|
377 |
}
|
sl@0
|
378 |
|
sl@0
|
379 |
|
sl@0
|
380 |
CRoutingSoundPlayDevice* CMMFSwCodecPlayDataPath::Device()
|
sl@0
|
381 |
{
|
sl@0
|
382 |
return iSoundDevice;
|
sl@0
|
383 |
}
|
sl@0
|
384 |
|
sl@0
|
385 |
void CMMFSwCodecPlayDataPath::SoundDeviceException(TInt aError)
|
sl@0
|
386 |
{
|
sl@0
|
387 |
//this sends a request to the hw device observer usually Devsound
|
sl@0
|
388 |
//to update the bytes played
|
sl@0
|
389 |
//it is done here so that the sound driver can be closed prior to
|
sl@0
|
390 |
//updating the plicy and sending the error back
|
sl@0
|
391 |
TUid uidUpdateBytesPlayed;
|
sl@0
|
392 |
uidUpdateBytesPlayed.iUid = KMmfHwDeviceObserverUpdateBytesPlayed;
|
sl@0
|
393 |
TPtrC8 dummy(0,0);
|
sl@0
|
394 |
iHwDeviceObserver->MsgFromHwDevice(uidUpdateBytesPlayed,dummy);
|
sl@0
|
395 |
|
sl@0
|
396 |
//this closes RMdaDevSound.
|
sl@0
|
397 |
Stop();
|
sl@0
|
398 |
|
sl@0
|
399 |
//inform devsound so it can update policy
|
sl@0
|
400 |
iHwDeviceObserver->Stopped();
|
sl@0
|
401 |
|
sl@0
|
402 |
// Inform the observer of the exception condition
|
sl@0
|
403 |
// We inform the hw device observer after the policy has been
|
sl@0
|
404 |
// updated incase the observer relied on the error to assume
|
sl@0
|
405 |
// the policy has been updated
|
sl@0
|
406 |
iHwDeviceObserver->Error(aError);
|
sl@0
|
407 |
}
|
sl@0
|
408 |
|
sl@0
|
409 |
|
sl@0
|
410 |
void CMMFSwCodecPlayDataPath::SetPlayCustomInterface(MPlayCustomInterface& aCustomInterface)
|
sl@0
|
411 |
{
|
sl@0
|
412 |
iCustomInterface = &aCustomInterface;
|
sl@0
|
413 |
}
|
sl@0
|
414 |
|
sl@0
|
415 |
void CMMFSwCodecPlayDataPath::SetConfigForAudioRamp(TUint aSampleRate, TUint aChannels)
|
sl@0
|
416 |
{
|
sl@0
|
417 |
iSampleRate = aSampleRate;
|
sl@0
|
418 |
iChannels = aChannels;
|
sl@0
|
419 |
}
|
sl@0
|
420 |
|
sl@0
|
421 |
/************************************************************************
|
sl@0
|
422 |
* CDataPathPlayer *
|
sl@0
|
423 |
************************************************************************/
|
sl@0
|
424 |
|
sl@0
|
425 |
CDataPathPlayer::CDataPathPlayer(CMMFSwCodecPlayDataPath& aParent, TInt aPriority)
|
sl@0
|
426 |
: CActive(aPriority), iParent(aParent)
|
sl@0
|
427 |
{
|
sl@0
|
428 |
CActiveScheduler::Add(this);
|
sl@0
|
429 |
}
|
sl@0
|
430 |
|
sl@0
|
431 |
|
sl@0
|
432 |
CDataPathPlayer::~CDataPathPlayer()
|
sl@0
|
433 |
{
|
sl@0
|
434 |
Cancel();
|
sl@0
|
435 |
}
|
sl@0
|
436 |
|
sl@0
|
437 |
|
sl@0
|
438 |
void CDataPathPlayer::Start()
|
sl@0
|
439 |
{
|
sl@0
|
440 |
// No implementation
|
sl@0
|
441 |
}
|
sl@0
|
442 |
|
sl@0
|
443 |
|
sl@0
|
444 |
void CDataPathPlayer::ResumePlaying()
|
sl@0
|
445 |
{
|
sl@0
|
446 |
if (iParent.Device()->Handle())
|
sl@0
|
447 |
{
|
sl@0
|
448 |
//should be ok to call this even if we are active
|
sl@0
|
449 |
iParent.Device()->ResumePlaying();
|
sl@0
|
450 |
iResumePlaying = ETrue;
|
sl@0
|
451 |
}
|
sl@0
|
452 |
#ifdef _SCW_DEBUG
|
sl@0
|
453 |
RDebug::Print(_L("Playing Resumed"));
|
sl@0
|
454 |
#endif
|
sl@0
|
455 |
}
|
sl@0
|
456 |
|
sl@0
|
457 |
|
sl@0
|
458 |
void CDataPathPlayer::PlayData(const CMMFDataBuffer& aData)
|
sl@0
|
459 |
{
|
sl@0
|
460 |
iDataFromSource = &aData;
|
sl@0
|
461 |
if (!IsActive())
|
sl@0
|
462 |
{
|
sl@0
|
463 |
#ifdef _SCW_DEBUG
|
sl@0
|
464 |
RDebug::Print(_L("CDataPathPlayer::PlayData"));
|
sl@0
|
465 |
#endif
|
sl@0
|
466 |
iParent.Device()->PlayData(aData.Data(), iStatus);
|
sl@0
|
467 |
SetActive();
|
sl@0
|
468 |
}
|
sl@0
|
469 |
}
|
sl@0
|
470 |
|
sl@0
|
471 |
|
sl@0
|
472 |
void CDataPathPlayer::Stop()
|
sl@0
|
473 |
{
|
sl@0
|
474 |
if (!IsActive())
|
sl@0
|
475 |
{
|
sl@0
|
476 |
iParent.Device()->FlushBuffer();
|
sl@0
|
477 |
}
|
sl@0
|
478 |
Cancel();
|
sl@0
|
479 |
iParent.SoundDeviceException(KErrCancel);
|
sl@0
|
480 |
}
|
sl@0
|
481 |
|
sl@0
|
482 |
|
sl@0
|
483 |
void CDataPathPlayer::RunL()
|
sl@0
|
484 |
{
|
sl@0
|
485 |
#ifdef _SCW_DEBUG
|
sl@0
|
486 |
RDebug::Print(_L("CDataPathPlayer::RunL error[%d]"), iStatus.Int());
|
sl@0
|
487 |
#endif
|
sl@0
|
488 |
if (!iStatus.Int())
|
sl@0
|
489 |
{
|
sl@0
|
490 |
iParent.BufferEmptiedL(static_cast<const CMMFDataBuffer&>(*iDataFromSource));
|
sl@0
|
491 |
iResumePlaying = EFalse;
|
sl@0
|
492 |
}
|
sl@0
|
493 |
//if we don't have a sound driver handle then we have stopped
|
sl@0
|
494 |
//but the client still thinks we are recording so swallow error
|
sl@0
|
495 |
else if (iStatus.Int()!= KErrBadHandle)
|
sl@0
|
496 |
{
|
sl@0
|
497 |
iParent.SoundDeviceException(iStatus.Int());
|
sl@0
|
498 |
}
|
sl@0
|
499 |
}
|
sl@0
|
500 |
|
sl@0
|
501 |
|
sl@0
|
502 |
TInt CDataPathPlayer::RunError(TInt aError)
|
sl@0
|
503 |
{
|
sl@0
|
504 |
Error(aError);
|
sl@0
|
505 |
return KErrNone;
|
sl@0
|
506 |
}
|
sl@0
|
507 |
|
sl@0
|
508 |
|
sl@0
|
509 |
void CDataPathPlayer::DoCancel()
|
sl@0
|
510 |
{
|
sl@0
|
511 |
if (iParent.Device()->Handle())
|
sl@0
|
512 |
{
|
sl@0
|
513 |
iParent.Device()->CancelPlayData();
|
sl@0
|
514 |
iParent.Device()->FlushBuffer();
|
sl@0
|
515 |
}
|
sl@0
|
516 |
}
|
sl@0
|
517 |
|
sl@0
|
518 |
|
sl@0
|
519 |
void CDataPathPlayer::Error(TInt aError)
|
sl@0
|
520 |
{
|
sl@0
|
521 |
iParent.SoundDeviceException(aError);
|
sl@0
|
522 |
}
|
sl@0
|
523 |
|
sl@0
|
524 |
|
sl@0
|
525 |
/************************************************************************
|
sl@0
|
526 |
* CSoundDevPlayErrorReceiver *
|
sl@0
|
527 |
************************************************************************/
|
sl@0
|
528 |
|
sl@0
|
529 |
CSoundDevPlayErrorReceiver::CSoundDevPlayErrorReceiver(CMMFSwCodecPlayDataPath& aParent, TInt aPriority)
|
sl@0
|
530 |
: CActive(aPriority), iParent(aParent)
|
sl@0
|
531 |
{
|
sl@0
|
532 |
CActiveScheduler::Add(this);
|
sl@0
|
533 |
}
|
sl@0
|
534 |
|
sl@0
|
535 |
CSoundDevPlayErrorReceiver::~CSoundDevPlayErrorReceiver()
|
sl@0
|
536 |
{
|
sl@0
|
537 |
Cancel();
|
sl@0
|
538 |
}
|
sl@0
|
539 |
|
sl@0
|
540 |
void CSoundDevPlayErrorReceiver::Start()
|
sl@0
|
541 |
{
|
sl@0
|
542 |
iParent.Device()->NotifyError(iStatus);
|
sl@0
|
543 |
SetActive();
|
sl@0
|
544 |
}
|
sl@0
|
545 |
|
sl@0
|
546 |
void CSoundDevPlayErrorReceiver::Stop()
|
sl@0
|
547 |
{
|
sl@0
|
548 |
Cancel();
|
sl@0
|
549 |
}
|
sl@0
|
550 |
|
sl@0
|
551 |
void CSoundDevPlayErrorReceiver::RunL()
|
sl@0
|
552 |
{
|
sl@0
|
553 |
// An error has been returned
|
sl@0
|
554 |
#ifdef _SCW_DEBUG
|
sl@0
|
555 |
RDebug::Print(_L("CSoundDevPlayErrorReceiver::RunL[%d]"), iStatus.Int());
|
sl@0
|
556 |
#endif
|
sl@0
|
557 |
iParent.SoundDeviceException(iStatus.Int());
|
sl@0
|
558 |
}
|
sl@0
|
559 |
|
sl@0
|
560 |
void CSoundDevPlayErrorReceiver::DoCancel()
|
sl@0
|
561 |
{
|
sl@0
|
562 |
iParent.Device()->CancelNotifyError();
|
sl@0
|
563 |
}
|
sl@0
|
564 |
|
sl@0
|
565 |
|