|
1 /* |
|
2 * Copyright (c) 2002-2005 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: Audio Stubs - |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 |
|
20 // INCLUDE FILES |
|
21 #include "MmfHwDeviceStub.h" |
|
22 #ifdef _DEBUG |
|
23 #include "e32debug.h" |
|
24 |
|
25 #define DEBPRN0(str) RDebug::Print(str, this) |
|
26 #define DEBPRN1(str, val1) RDebug::Print(str, this, val1) |
|
27 #define DEBPRN2(str, val1, val2) RDebug::Print(str, this, val1, val2) |
|
28 #else |
|
29 #define DEBPRN0(str) |
|
30 #define DEBPRN1(str, val1) |
|
31 #define DEBPRN2(str, val1, val2) |
|
32 #endif //_DEBUG |
|
33 |
|
34 // CONSTANTS |
|
35 const TUint KBufferLength1 = 0x1000; |
|
36 const TUint KBufferLength2 = 0x1000; |
|
37 //const TUint KBufferLength2 = 0x1800; // for creating second buffer with different length than the first buffer. |
|
38 const TUint KTimerDuration = 200000; |
|
39 |
|
40 #ifdef __WINSCW__ |
|
41 _LIT(KSample1,"C:\\sample1.wav"); |
|
42 #else |
|
43 _LIT(KSample1,"Z:\\system\\data\\DevSoundAdaptationStub\\sample1.wav"); |
|
44 #endif // __WINSCW__ |
|
45 |
|
46 // ============================ MEMBER FUNCTIONS =============================== |
|
47 |
|
48 // ----------------------------------------------------------------------------- |
|
49 // CMMFHwDeviceStub::CMMFHwDeviceStub |
|
50 // C++ default constructor can NOT contain any code, that |
|
51 // might leave. |
|
52 // ----------------------------------------------------------------------------- |
|
53 // |
|
54 CMMFHwDeviceStub::CMMFHwDeviceStub() |
|
55 : CActive(EPriorityNormal), iHwDeviceState(EHWDeviceIdle), iCurPlayBuffer(NULL), |
|
56 iCurRecdBuffer(NULL) |
|
57 { |
|
58 CActiveScheduler::Add(this); |
|
59 } |
|
60 |
|
61 // ----------------------------------------------------------------------------- |
|
62 // CMMFHwDeviceStub::ConstructL |
|
63 // Symbian 2nd phase constructor can leave. |
|
64 // ----------------------------------------------------------------------------- |
|
65 // |
|
66 void CMMFHwDeviceStub::ConstructL() |
|
67 { |
|
68 DEBPRN0(_L("CMMFHwDeviceStub[0x%x]::ConstructL:BEGIN")); |
|
69 // Create timer |
|
70 User::LeaveIfError(iTimer.CreateLocal()); |
|
71 DEBPRN0(_L("CMMFHwDeviceStub[0x%x]::ConstructL:END")); |
|
72 } |
|
73 |
|
74 // ----------------------------------------------------------------------------- |
|
75 // CMMFHwDeviceStub::NewL |
|
76 // Two-phased constructor. |
|
77 // ----------------------------------------------------------------------------- |
|
78 // |
|
79 CMMFHwDeviceStub* CMMFHwDeviceStub::NewL() |
|
80 { |
|
81 CMMFHwDeviceStub* self = new (ELeave)CMMFHwDeviceStub; |
|
82 CleanupStack::PushL(self); |
|
83 self->ConstructL(); |
|
84 CleanupStack::Pop(self); |
|
85 return self; |
|
86 } |
|
87 |
|
88 // ----------------------------------------------------------------------------- |
|
89 // CMMFHwDeviceStub::~CMMFHwDeviceStub |
|
90 // Destructor |
|
91 // ----------------------------------------------------------------------------- |
|
92 // |
|
93 CMMFHwDeviceStub::~CMMFHwDeviceStub() |
|
94 { |
|
95 DEBPRN0(_L("CMMFHwDeviceStub[0x%x]::~CMMFHwDeviceStub:BEGIN")); |
|
96 // Cancel A/O and close the timer |
|
97 Cancel(); |
|
98 iTimer.Close(); |
|
99 |
|
100 // Delete buffers |
|
101 delete iPlayBuffer1; |
|
102 delete iPlayBuffer2; |
|
103 delete iRecdBuffer1; |
|
104 delete iRecdBuffer2; |
|
105 |
|
106 DEBPRN0(_L("CMMFHwDeviceStub[0x%x]::~CMMFHwDeviceStub:END")); |
|
107 } |
|
108 |
|
109 //----------------------------------------------------------------------------- |
|
110 // CMMFHwDeviceStub::Start |
|
111 // Starts playback/record based on aFuncCmd |
|
112 // (other items were commented in a header). |
|
113 //----------------------------------------------------------------------------- |
|
114 TInt CMMFHwDeviceStub::Start(TDeviceFunc aFuncCmd, TDeviceFlow /*aFlowCmd*/) |
|
115 { |
|
116 DEBPRN0(_L("CMMFHwDeviceStub[0x%x]::Start:BEGIN")); |
|
117 TInt status(KErrNone); |
|
118 switch(aFuncCmd) |
|
119 { |
|
120 case EDevDecode: |
|
121 iCurPlayBuffer = NULL; |
|
122 |
|
123 // Initialize buffers |
|
124 TRAP(status, InitializePlayBufferL()); |
|
125 if (status != KErrNone) |
|
126 return status; |
|
127 |
|
128 // Reset buffers rendered count to zero only if not pause-continue |
|
129 if (iHwDeviceState == EHWDeviceIdle) |
|
130 iCount = 0; |
|
131 // Initialize attributes |
|
132 iHwDeviceState = EHWDevicePlay; |
|
133 iLastBufferReceived = EFalse; |
|
134 // If not already active, launch timer |
|
135 if (!IsActive()) |
|
136 { |
|
137 iTimer.After(iStatus,TTimeIntervalMicroSeconds32(KTimerDuration) ); |
|
138 SetActive(); |
|
139 } |
|
140 break; |
|
141 case EDevEncode: |
|
142 iCurRecdBuffer = NULL; |
|
143 |
|
144 // Initialize buffers |
|
145 TRAP(status, InitializeRecdBufferL()); |
|
146 if (status != KErrNone) |
|
147 return status; |
|
148 |
|
149 // Reset buffers rendered count to zero only if not pause-continue |
|
150 if (iHwDeviceState == EHWDeviceIdle) |
|
151 iCount = 0; |
|
152 // Initialize attributes |
|
153 iHwDeviceState = EHWDeviceRecord; |
|
154 // If not already active, launch timer |
|
155 if (!IsActive()) |
|
156 { |
|
157 iTimer.After(iStatus,TTimeIntervalMicroSeconds32(KTimerDuration) ); |
|
158 SetActive(); |
|
159 } |
|
160 break; |
|
161 default: |
|
162 status = KErrNotSupported; |
|
163 break; |
|
164 }; |
|
165 DEBPRN0(_L("CMMFHwDeviceStub[0x%x]::Start:END")); |
|
166 return status; |
|
167 } |
|
168 |
|
169 //----------------------------------------------------------------------------- |
|
170 // CMMFHwDeviceStub::Stop |
|
171 // Stops current operation. |
|
172 // (other items were commented in a header). |
|
173 //----------------------------------------------------------------------------- |
|
174 TInt CMMFHwDeviceStub::Stop() |
|
175 { |
|
176 DEBPRN0(_L("CMMFHwDeviceStub[0x%x]::Stop")); |
|
177 TInt status(KErrNone); |
|
178 // Cancel any outstanding requests |
|
179 Cancel(); |
|
180 // Reset attributes |
|
181 iHwDeviceState = EHWDeviceIdle; |
|
182 iLastBufferReceived = EFalse; |
|
183 iCurPlayBuffer = NULL; |
|
184 iCurRecdBuffer = NULL; |
|
185 // Notify observer Stopped |
|
186 iObserver->Stopped(); |
|
187 return status; |
|
188 } |
|
189 |
|
190 //----------------------------------------------------------------------------- |
|
191 // CMMFHwDeviceStub::Pause |
|
192 // Pauses current operation. |
|
193 // (other items were commented in a header). |
|
194 //----------------------------------------------------------------------------- |
|
195 TInt CMMFHwDeviceStub::Pause() |
|
196 { |
|
197 DEBPRN0(_L("CMMFHwDeviceStub[0x%x]::Pause")); |
|
198 TInt status(KErrNone); |
|
199 |
|
200 // Fix to WAV recording issue. |
|
201 // Proper way to stop this A/O is by letting the data path to call back |
|
202 // Stop() after detecting last buffer. |
|
203 // Cancel(); |
|
204 return status; |
|
205 } |
|
206 |
|
207 //----------------------------------------------------------------------------- |
|
208 // CMMFHwDeviceStub::Init |
|
209 // Initializes CMMFHwDevice. |
|
210 // (other items were commented in a header). |
|
211 //----------------------------------------------------------------------------- |
|
212 TInt CMMFHwDeviceStub::Init(THwDeviceInitParams& aDevInfo) |
|
213 { |
|
214 DEBPRN0(_L("CMMFHwDeviceStub[0x%x]::Init")); |
|
215 TInt status(KErrNone); |
|
216 iObserver = aDevInfo.iHwDeviceObserver; |
|
217 return status; |
|
218 } |
|
219 |
|
220 //----------------------------------------------------------------------------- |
|
221 // CMMFHwDeviceStub::CustomInterface |
|
222 // Returns a pointer to CustomInterface. |
|
223 // (other items were commented in a header). |
|
224 //----------------------------------------------------------------------------- |
|
225 TAny* CMMFHwDeviceStub::CustomInterface(TUid /*aInterfaceId*/) |
|
226 { |
|
227 return NULL; |
|
228 } |
|
229 |
|
230 //----------------------------------------------------------------------------- |
|
231 // CMMFHwDeviceStub::ThisHwBufferFilled |
|
232 // Returns a pointer to CustomInterface. |
|
233 // (other items were commented in a header). |
|
234 //----------------------------------------------------------------------------- |
|
235 TInt CMMFHwDeviceStub::ThisHwBufferFilled(CMMFBuffer& aFillBufferPtr) |
|
236 { |
|
237 DEBPRN2(_L("CMMFHwDeviceStub[0x%x]::ThisHwBufferFilled:Addr[0x%x]Count[%d]"), iCurPlayBuffer, ++iCount); |
|
238 TInt status(KErrNotReady); |
|
239 if (iHwDeviceState == EHWDevicePlay) |
|
240 { |
|
241 status = KErrNone; |
|
242 if (aFillBufferPtr.LastBuffer()) |
|
243 { |
|
244 iLastBufferReceived = ETrue; |
|
245 DEBPRN0(_L("CMMFHwDeviceStub[0x%x]::ThisHwBufferFilled[LastBuffer]")); |
|
246 } |
|
247 |
|
248 // If not already active, launch timer |
|
249 if (!IsActive()) |
|
250 { |
|
251 iTimer.After(iStatus,TTimeIntervalMicroSeconds32(KTimerDuration) ); |
|
252 SetActive(); |
|
253 } |
|
254 } |
|
255 return status; |
|
256 } |
|
257 |
|
258 //----------------------------------------------------------------------------- |
|
259 // CMMFHwDeviceStub::ThisHwBufferEmptied |
|
260 // Called by client when data is available during recording. |
|
261 // (other items were commented in a header). |
|
262 //----------------------------------------------------------------------------- |
|
263 TInt CMMFHwDeviceStub::ThisHwBufferEmptied(CMMFBuffer& aEmptyBufferPtr) |
|
264 { |
|
265 DEBPRN1(_L("CMMFHwDeviceStub[0x%x]::ThisHwBufferEmptied[%d]"), ++iCount); |
|
266 TInt status(KErrNotReady); |
|
267 if (iHwDeviceState == EHWDeviceRecord) |
|
268 { |
|
269 status = KErrNone; |
|
270 |
|
271 // Fix to WAV recording issue. |
|
272 // In case of real DevSound adaptation implementation, the |
|
273 // CMMFSwCodecRecordDataPath sets the last buffer parameter when no |
|
274 // more data is in the buffer to process. In case of the stub, this |
|
275 // never gets set as the s/w codec is not involved - we are simply |
|
276 // copying same fixed 4k block of data over and over again. So, on |
|
277 // pause or stop we need to indicate to the data path that we no |
|
278 // longer need processing of data by manually setting last buffer |
|
279 // parameter and resetting requested data size to 0. |
|
280 if (aEmptyBufferPtr.LastBuffer()) |
|
281 { |
|
282 iRecdBuffer1->SetLastBuffer(ETrue); |
|
283 iRecdBuffer1->SetRequestSizeL(0); |
|
284 iRecdBuffer2->SetLastBuffer(ETrue); |
|
285 iRecdBuffer2->SetRequestSizeL(0); |
|
286 } |
|
287 |
|
288 // If not already active, launch timer |
|
289 if (!IsActive()) |
|
290 { |
|
291 iTimer.After(iStatus,TTimeIntervalMicroSeconds32(KTimerDuration) ); |
|
292 SetActive(); |
|
293 } |
|
294 } |
|
295 |
|
296 return status; |
|
297 } |
|
298 |
|
299 //----------------------------------------------------------------------------- |
|
300 // CMMFHwDeviceStub::SetConfig |
|
301 // Configures CMMFHwDevice. |
|
302 // (other items were commented in a header). |
|
303 //----------------------------------------------------------------------------- |
|
304 TInt CMMFHwDeviceStub::SetConfig(TTaskConfig& /*aConfig*/) |
|
305 { |
|
306 DEBPRN0(_L("CMMFHwDeviceStub[0x%x]::SetConfig")); |
|
307 TInt status(KErrNone); |
|
308 return status; |
|
309 } |
|
310 |
|
311 //----------------------------------------------------------------------------- |
|
312 // CMMFHwDeviceStub::StopAndDeleteCodec |
|
313 // Stops and deletes codec. |
|
314 // (other items were commented in a header). |
|
315 //----------------------------------------------------------------------------- |
|
316 TInt CMMFHwDeviceStub::StopAndDeleteCodec() |
|
317 { |
|
318 DEBPRN0(_L("CMMFHwDeviceStub[0x%x]::StopAndDeleteCodec")); |
|
319 TInt status(KErrNone); |
|
320 Stop(); |
|
321 return status; |
|
322 } |
|
323 |
|
324 //----------------------------------------------------------------------------- |
|
325 // CMMFHwDeviceStub::DeleteCodec |
|
326 // Deletes codec. |
|
327 // (other items were commented in a header). |
|
328 //----------------------------------------------------------------------------- |
|
329 TInt CMMFHwDeviceStub::DeleteCodec() |
|
330 { |
|
331 DEBPRN0(_L("CMMFHwDeviceStub[0x%x]::DeleteCodec")); |
|
332 TInt status(KErrNone); |
|
333 Stop(); |
|
334 return status; |
|
335 } |
|
336 |
|
337 |
|
338 //----------------------------------------------------------------------------- |
|
339 // CMMFHwDeviceStub::RunL |
|
340 // Called by CActive object framework when local timer times out. |
|
341 // (other items were commented in a header). |
|
342 //----------------------------------------------------------------------------- |
|
343 void CMMFHwDeviceStub::RunL() |
|
344 { |
|
345 DEBPRN1(_L("CMMFHwDeviceStub[0x%x]::RunL:iHwDevState[%d]"), iHwDeviceState); |
|
346 switch(iHwDeviceState) |
|
347 { |
|
348 case EHWDevicePlay: |
|
349 // If last buffer is received, send error |
|
350 if (iLastBufferReceived) |
|
351 { |
|
352 iObserver->Error(KErrUnderflow); |
|
353 Stop(); |
|
354 } |
|
355 else |
|
356 { |
|
357 SetActivePlayBufferL(); |
|
358 iObserver->FillThisHwBuffer(*iCurPlayBuffer); |
|
359 } |
|
360 break; |
|
361 case EHWDeviceRecord: |
|
362 SetActiveRecdBufferL(); |
|
363 iObserver->EmptyThisHwBuffer(*iCurRecdBuffer); |
|
364 break; |
|
365 default: |
|
366 break; |
|
367 } |
|
368 } |
|
369 |
|
370 //----------------------------------------------------------------------------- |
|
371 // CMMFHwDeviceStub::DoCancel |
|
372 // From CActive. Called by Framework when this instance is active and is |
|
373 // cancelled |
|
374 //----------------------------------------------------------------------------- |
|
375 void CMMFHwDeviceStub::DoCancel() |
|
376 { |
|
377 DEBPRN0(_L("CMMFHwDeviceStub[0x%x]::DoCancel")); |
|
378 iTimer.Cancel(); |
|
379 } |
|
380 |
|
381 //----------------------------------------------------------------------------- |
|
382 // CMMFHwDeviceStub::Error |
|
383 // From CActive. Called by Framework when RunL Leaves |
|
384 //----------------------------------------------------------------------------- |
|
385 TInt CMMFHwDeviceStub::Error(TInt /*aError*/) |
|
386 { |
|
387 return KErrNone; |
|
388 } |
|
389 |
|
390 //----------------------------------------------------------------------------- |
|
391 // CMMFHwDeviceStub::InitializePlayBufferL |
|
392 // Initializes buffer(s) used for playback |
|
393 //----------------------------------------------------------------------------- |
|
394 void CMMFHwDeviceStub::InitializePlayBufferL() |
|
395 { |
|
396 if (!iPlayBuffer1) |
|
397 { |
|
398 // Create buffers |
|
399 iPlayBuffer1 = CMMFDataBuffer::NewL(KBufferLength1); |
|
400 } |
|
401 if (!iPlayBuffer2) |
|
402 { |
|
403 // Create buffers |
|
404 iPlayBuffer2 = CMMFDataBuffer::NewL(KBufferLength2); |
|
405 } |
|
406 } |
|
407 |
|
408 //----------------------------------------------------------------------------- |
|
409 // CMMFHwDeviceStub::InitializeRecdBufferL |
|
410 // Initializes buffer(s) used for recording |
|
411 //----------------------------------------------------------------------------- |
|
412 void CMMFHwDeviceStub::InitializeRecdBufferL() |
|
413 { |
|
414 if (!iRecdBuffer1) |
|
415 { |
|
416 DEBPRN0(_L("CMMFHwDeviceStub[0x%x]::InitializeRecdBufferL:Creating buffer...")); |
|
417 // Create buffers |
|
418 iRecdBuffer1 = CMMFDataBuffer::NewL(KBufferLength1); |
|
419 } |
|
420 |
|
421 if (!iRecdBuffer2) |
|
422 { |
|
423 DEBPRN0(_L("CMMFHwDeviceStub[0x%x]::InitializeRecdBufferL:Creating buffer...")); |
|
424 // Create buffers |
|
425 iRecdBuffer2 = CMMFDataBuffer::NewL(KBufferLength2); |
|
426 } |
|
427 |
|
428 iPosition = 0; |
|
429 |
|
430 } |
|
431 |
|
432 //----------------------------------------------------------------------------- |
|
433 // CMMFHwDeviceStub::SetActiveRecdBufferL |
|
434 // Reads data from the input file to the buffer |
|
435 //----------------------------------------------------------------------------- |
|
436 void CMMFHwDeviceStub::SetActiveRecdBufferL() |
|
437 { |
|
438 if ( !iCurRecdBuffer || ( iCurRecdBuffer == iRecdBuffer2 ) ) |
|
439 { |
|
440 iCurRecdBuffer = iRecdBuffer1; |
|
441 } |
|
442 else |
|
443 { |
|
444 iCurRecdBuffer = iRecdBuffer2; |
|
445 } |
|
446 |
|
447 if ( !iCurRecdBuffer->LastBuffer() ) |
|
448 { |
|
449 RFs rFs; |
|
450 RFile rFile; |
|
451 User::LeaveIfError(rFs.Connect()); |
|
452 User::LeaveIfError(rFile.Open(rFs, KSample1, EFileRead)); |
|
453 |
|
454 TInt size; |
|
455 User::LeaveIfError(rFile.Size(size)); |
|
456 TInt bufLength( iCurRecdBuffer->Data().MaxLength() ); |
|
457 if (iPosition > (size - bufLength)) |
|
458 { |
|
459 iPosition = 0; //rewind file position index to the beginning |
|
460 } |
|
461 // Assumption, file size is more than iCurRecdBuffer->Data().MaxLength() |
|
462 User::LeaveIfError(rFile.Read(iPosition, |
|
463 iCurRecdBuffer->Data(), |
|
464 bufLength) ); |
|
465 iCurRecdBuffer->SetRequestSizeL(bufLength); |
|
466 iCurRecdBuffer->SetLastBuffer(EFalse); |
|
467 rFile.Close(); |
|
468 rFs.Close(); |
|
469 |
|
470 iPosition += bufLength; |
|
471 } |
|
472 } |
|
473 |
|
474 //----------------------------------------------------------------------------- |
|
475 // CMMFHwDeviceStub::SetActivePlayBufferL |
|
476 // Reads data from the input file to the buffer |
|
477 //----------------------------------------------------------------------------- |
|
478 void CMMFHwDeviceStub::SetActivePlayBufferL() |
|
479 { |
|
480 if ( !iCurPlayBuffer || ( iCurPlayBuffer == iPlayBuffer2 ) ) |
|
481 { |
|
482 iCurPlayBuffer = iPlayBuffer1; |
|
483 } |
|
484 else |
|
485 { |
|
486 iCurPlayBuffer = iPlayBuffer2; |
|
487 } |
|
488 iCurPlayBuffer->SetRequestSizeL(iCurPlayBuffer->Data().MaxLength()); |
|
489 iCurPlayBuffer->Data().SetLength(0); |
|
490 iCurPlayBuffer->SetLastBuffer(EFalse); |
|
491 } |
|
492 |
|
493 //End of File |