|
1 // Copyright (c) 1997-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 |
|
17 #include <f32file.h> |
|
18 #include <e32std.h> |
|
19 #include <mmf/server/mmfdes.h> |
|
20 #include <mmf/server/mmfdatabuffer.h> |
|
21 #include <mmf/common/mmfpaniccodes.h> |
|
22 |
|
23 void Panic(TMMFDescriptorPanicCode aPanicCode) |
|
24 { |
|
25 _LIT(KMMFDescriptorPanicCategory, "MMFDescriptor"); |
|
26 User::Panic(KMMFDescriptorPanicCategory, aPanicCode); |
|
27 } |
|
28 |
|
29 /** |
|
30 Protected constructor. |
|
31 |
|
32 Sets the offset to zero. |
|
33 */ |
|
34 CMMFDescriptor::CMMFDescriptor( ) : CMMFClip( KUidMmfDescriptorSource, KUidMmfDescriptorSink ) |
|
35 { |
|
36 } |
|
37 |
|
38 /** |
|
39 Destructor. |
|
40 |
|
41 The default implementation closes the descriptor thread. |
|
42 */ |
|
43 CMMFDescriptor::~CMMFDescriptor() |
|
44 { |
|
45 iDesThread.Close() ; |
|
46 } |
|
47 |
|
48 /** |
|
49 Constructs a CMMFDescriptor MDataSource. |
|
50 |
|
51 @return A pointer to a new CMMFDescriptor. |
|
52 */ |
|
53 MDataSource* CMMFDescriptor::NewSourceL( ) |
|
54 { |
|
55 CMMFDescriptor* self = new (ELeave) CMMFDescriptor( ) ; |
|
56 return STATIC_CAST( MDataSource*, self ) ; |
|
57 } |
|
58 |
|
59 /** |
|
60 Constructs a CMMFDescriptor MDataSink. |
|
61 |
|
62 @return A pointer to a new CMMFDescriptor. |
|
63 */ |
|
64 MDataSink* CMMFDescriptor::NewSinkL( ) |
|
65 { |
|
66 CMMFDescriptor* self = new (ELeave) CMMFDescriptor( ) ; |
|
67 return STATIC_CAST( MDataSink*, self ) ; |
|
68 } |
|
69 |
|
70 /** |
|
71 Performs source construction dependant on the source construction |
|
72 initialisation data aInitData. |
|
73 |
|
74 @param aInitData |
|
75 The TPckgC<TMMFDescriptorParams> descriptor package containing the descriptor and the thread |
|
76 ID for the descriptor. |
|
77 */ |
|
78 void CMMFDescriptor::ConstructSourceL( const TDesC8& aInitData ) |
|
79 { |
|
80 ConstructL( aInitData ) ; |
|
81 } |
|
82 |
|
83 |
|
84 /*** |
|
85 Sets how much of the underlying descriptor will be used, up to the underlying descriptor's maximum |
|
86 length. |
|
87 |
|
88 @param aSize |
|
89 The size of the descriptor. |
|
90 |
|
91 @return An error code indicating if the function call was successful. KErrNone on success, otherwise |
|
92 another of the system-wide error codes. |
|
93 */ |
|
94 TInt CMMFDescriptor::SetSize( TInt aSize ) |
|
95 { |
|
96 //[ precondition aSize >= 0 |
|
97 // precondition sSize < MaxSize() |
|
98 // iDes is not null] |
|
99 if(!iDes ) |
|
100 return KErrNotReady; |
|
101 |
|
102 if( aSize > MaxLength() ) |
|
103 return KErrOverflow; |
|
104 |
|
105 if( aSize < 0 ) |
|
106 return KErrUnderflow; |
|
107 |
|
108 // [ actually do the work ] |
|
109 iDes->SetLength( aSize ); |
|
110 |
|
111 //[ assert the post condition |
|
112 // aSize == Length() |
|
113 // descriptor is still ok] |
|
114 ASSERT( aSize == iDes->Length()); |
|
115 ASSERT( iDes ); |
|
116 |
|
117 return KErrNone; |
|
118 } |
|
119 |
|
120 |
|
121 /** |
|
122 Performs sink construction dependant on the sink construction initialisation data aInitData. |
|
123 |
|
124 @param aInitData |
|
125 The TPckgC<TMMFDescriptorParams> descriptor package containing |
|
126 the descriptor and the thread ID for the descriptor. |
|
127 */ |
|
128 void CMMFDescriptor::ConstructSinkL( const TDesC8& aInitData ) |
|
129 { |
|
130 ConstructL( aInitData ) ; |
|
131 } |
|
132 |
|
133 void CMMFDescriptor::ConstructL( const TDesC8& aInitData ) |
|
134 { |
|
135 TMMFDescriptorParams params; |
|
136 TPckgC<TMMFDescriptorParams> config(params); |
|
137 if (aInitData.Length() < config.Length()) |
|
138 User::Leave(KErrGeneral); |
|
139 config.Set(aInitData); |
|
140 iDes = STATIC_CAST( TDes8*, config().iDes); |
|
141 User::LeaveIfError( iDesThread.Open( config().iDesThreadId ) ); |
|
142 } |
|
143 |
|
144 |
|
145 /** |
|
146 Loads aBuffer from iDes. |
|
147 |
|
148 File read is asynchronous. CReadRequest is created to respond to completion. |
|
149 |
|
150 @param aBuffer |
|
151 The buffer to be filled from the descriptor. |
|
152 @param aConsumer |
|
153 The data sink consumer of the buffer. |
|
154 @param aMediaId |
|
155 Not used. |
|
156 */ |
|
157 void CMMFDescriptor::FillBufferL( CMMFBuffer* aBuffer, MDataSink* aConsumer, TMediaId /*aMediaId*/ ) |
|
158 { |
|
159 // Current position in Descriptor is iOffset. |
|
160 |
|
161 // Read from iDes in iDesThread into Des in aBuffer. |
|
162 |
|
163 // Assume that the amount to be read is the size of the buffer descriptor |
|
164 // Should check that there is sufficient data in the source buffer |
|
165 // If there is not enough to fill the target then copy what there is |
|
166 // How should the function deal with no data in the source buffer? |
|
167 |
|
168 // Use of a single iOffset will preclude use by more than one client (use ReadBufferL()) |
|
169 if (CMMFBuffer::IsSupportedDataBuffer(aBuffer->Type())) |
|
170 { |
|
171 TDes8& bufferDes = STATIC_CAST(CMMFDataBuffer*, aBuffer)->Data(); |
|
172 |
|
173 //if request size is set, use it, else use max length of buffer |
|
174 TInt targetMaxLength = aBuffer->RequestSize() ? aBuffer->RequestSize() : bufferDes.MaxLength(); |
|
175 |
|
176 //ensure RequestSize was within bounds |
|
177 if(targetMaxLength > bufferDes.MaxLength()) |
|
178 targetMaxLength = bufferDes.MaxLength(); |
|
179 |
|
180 TInt sourceLengthRemaining = iDes->Length() - iOffset; |
|
181 if ( ( sourceLengthRemaining - targetMaxLength ) > 0 ) |
|
182 { |
|
183 bufferDes = iDes->Mid(iOffset,targetMaxLength); |
|
184 iOffset += targetMaxLength; |
|
185 } |
|
186 else if (sourceLengthRemaining > 0) |
|
187 { |
|
188 bufferDes = iDes->Mid(iOffset,sourceLengthRemaining); |
|
189 iOffset += sourceLengthRemaining; |
|
190 aBuffer->SetLastBuffer(ETrue); |
|
191 } |
|
192 else |
|
193 { |
|
194 bufferDes.SetLength(0); |
|
195 aBuffer->SetLastBuffer(ETrue); |
|
196 } |
|
197 |
|
198 aConsumer->BufferFilledL( aBuffer ) ; |
|
199 } |
|
200 else |
|
201 User::Leave(KErrNotSupported); |
|
202 } |
|
203 |
|
204 /** |
|
205 Empties aBuffer into iDes. |
|
206 |
|
207 @param aBuffer |
|
208 The buffer to be written to the descriptor. |
|
209 @param aSupplier |
|
210 The data source supplier of the buffer. |
|
211 @param aMediaId |
|
212 The Media ID. |
|
213 */ |
|
214 void CMMFDescriptor::EmptyBufferL( CMMFBuffer* aBuffer, MDataSource* aSupplier, TMediaId /*aMediaId*/ ) |
|
215 { |
|
216 // Does the buffer type need to be checked? |
|
217 |
|
218 // Assume that the amount to be read is the size of the buffer descriptor |
|
219 // Should check that there is sufficient data in the source buffer |
|
220 // If there is not enough to fill the target then copy what there is |
|
221 // How should the function deal with no data in the source buffer? |
|
222 if (CMMFBuffer::IsSupportedDataBuffer(aBuffer->Type())) |
|
223 { |
|
224 TDes8& bufferDes = STATIC_CAST(CMMFDataBuffer*, aBuffer)->Data(); |
|
225 |
|
226 TInt sourceLength = bufferDes.Length() ; |
|
227 TInt targetLength = iDes->MaxLength() - iDes->Length(); |
|
228 if ( targetLength>0 ) |
|
229 { |
|
230 if (sourceLength>targetLength) |
|
231 { |
|
232 sourceLength = targetLength; |
|
233 bufferDes.SetLength(targetLength); |
|
234 } |
|
235 |
|
236 iDes->Append(bufferDes) ; |
|
237 } |
|
238 else |
|
239 bufferDes.SetLength(0); |
|
240 |
|
241 aSupplier->BufferEmptiedL( aBuffer ) ; |
|
242 } |
|
243 else |
|
244 User::Leave(KErrNotSupported); |
|
245 } |
|
246 |
|
247 /** |
|
248 Loads aLength number of bytes into aBuffer from specified point in iDes. |
|
249 |
|
250 @param aLength |
|
251 The number of bytes to be read into buffer. |
|
252 @param aBuffer |
|
253 The buffer to be filled from the descriptor. |
|
254 @param aPosition |
|
255 The offset into the descriptor at which to start reading. |
|
256 @param aConsumer |
|
257 The data sink consumer of the buffer |
|
258 */ |
|
259 void CMMFDescriptor::ReadBufferL(TInt aLength, CMMFBuffer* aBuffer, TInt aPosition, MDataSink* aConsumer) |
|
260 { |
|
261 if (!aBuffer) |
|
262 User::Leave(KErrArgument); |
|
263 |
|
264 if (CMMFBuffer::IsSupportedDataBuffer(aBuffer->Type())) |
|
265 { |
|
266 TDes8& bufferDes = STATIC_CAST(CMMFDataBuffer*, aBuffer)->Data(); |
|
267 |
|
268 if (aLength>bufferDes.MaxLength()) |
|
269 User::Leave(KErrOverflow); |
|
270 |
|
271 if ((aLength<0) || (aPosition<0)) |
|
272 User::Leave(KErrArgument); |
|
273 |
|
274 TInt sourceLength = iDes->Length() ; |
|
275 |
|
276 //ensure not trying to read more than is available |
|
277 if(aPosition + aLength > sourceLength) |
|
278 aLength = sourceLength - aPosition; |
|
279 |
|
280 if (aLength>0) |
|
281 { |
|
282 TPtrC8 srcPtr(iDes->Mid(aPosition,aLength)); |
|
283 bufferDes.Copy(srcPtr.Ptr(),aLength); |
|
284 } |
|
285 else |
|
286 bufferDes.SetLength(0); |
|
287 |
|
288 //have we read all the available data |
|
289 if(aPosition + aLength >= sourceLength) |
|
290 aBuffer->SetLastBuffer(ETrue); |
|
291 |
|
292 if (aConsumer) |
|
293 aConsumer->BufferFilledL(aBuffer); |
|
294 } |
|
295 else |
|
296 User::Leave(KErrNotSupported); |
|
297 } |
|
298 |
|
299 /** |
|
300 Loads aBuffer from specified point in iDes |
|
301 |
|
302 @param aBuffer |
|
303 The buffer to be filled from the descriptor. |
|
304 @param aPosition |
|
305 The offset into the descriptor at which to start reading. |
|
306 @param aConsumer |
|
307 The data sink consumer of the buffer. |
|
308 */ |
|
309 void CMMFDescriptor::ReadBufferL(CMMFBuffer* aBuffer, TInt aPosition, MDataSink* aConsumer) |
|
310 { |
|
311 if (!aBuffer) |
|
312 User::Leave(KErrArgument); |
|
313 |
|
314 if (aPosition<0) |
|
315 User::Leave(KErrArgument); |
|
316 |
|
317 if (CMMFBuffer::IsSupportedDataBuffer(aBuffer->Type())) |
|
318 { |
|
319 TDes8& bufferDes = STATIC_CAST(CMMFDataBuffer*, aBuffer)->Data(); |
|
320 //if request size is set, use it, else use max length of buffer |
|
321 TUint copyLength = aBuffer->RequestSize() ? aBuffer->RequestSize() : bufferDes.MaxLength(); |
|
322 |
|
323 ReadBufferL(copyLength, aBuffer, aPosition, aConsumer); |
|
324 } |
|
325 else |
|
326 User::Leave(KErrNotSupported); |
|
327 } |
|
328 |
|
329 /** |
|
330 Loads aBuffer from specified point in iDes. Note that this is a synchronous read. |
|
331 |
|
332 @param aBuffer |
|
333 The buffer to be filled from the descriptor. |
|
334 @param aPosition |
|
335 The offset into the descriptor at which to start reading. |
|
336 */ |
|
337 void CMMFDescriptor::ReadBufferL(CMMFBuffer* aBuffer, TInt aPosition) |
|
338 { |
|
339 ReadBufferL(aBuffer, aPosition, NULL); |
|
340 } |
|
341 |
|
342 /** |
|
343 Empties aBuffer into iDes at specified location. |
|
344 |
|
345 @param aBuffer |
|
346 The data buffer containing bytes to be written. |
|
347 @param aPosition |
|
348 The offset into the descriptor at which to start writing. |
|
349 @param aSupplier |
|
350 The data source to be notified when the write has been completed. |
|
351 */ |
|
352 void CMMFDescriptor::WriteBufferL(CMMFBuffer* aBuffer, TInt aPosition, MDataSource* aSupplier) |
|
353 { |
|
354 if (CMMFBuffer::IsSupportedDataBuffer(aBuffer->Type())) |
|
355 { |
|
356 TDes8& bufferDes = STATIC_CAST(CMMFDataBuffer*, aBuffer)->Data(); |
|
357 |
|
358 WriteBufferL(bufferDes.Length(), aBuffer, aPosition, aSupplier); |
|
359 } |
|
360 else |
|
361 User::Leave(KErrNotSupported); |
|
362 } |
|
363 |
|
364 /** |
|
365 Empties aLength bytes from aBuffer into iDes at specified location. |
|
366 |
|
367 @param aLength |
|
368 The number of bytes to be emptied from buffer. |
|
369 @param aBuffer |
|
370 The data buffer containing bytes to be written. |
|
371 @param aPosition |
|
372 The offset into the descriptor at which to start writing. |
|
373 @param aSupplier |
|
374 The data source to be notified when the write has been completed. |
|
375 |
|
376 @leave KErrNotReady |
|
377 If SinkPrimeL() and SinkThreadLogon() have not been called. |
|
378 @leave KErrArgument |
|
379 If aLength<0 or aPosition<0 or aSupplier is NULL. |
|
380 @leave KErrNotSupported |
|
381 If aBuffer is not of type KMMFDataBuffer. |
|
382 */ |
|
383 void CMMFDescriptor::WriteBufferL(TInt aLength, CMMFBuffer* aBuffer, TInt aPosition, MDataSource* aSupplier) |
|
384 { |
|
385 if (CMMFBuffer::IsSupportedDataBuffer(aBuffer->Type())) |
|
386 { |
|
387 TDes8& bufferDes = STATIC_CAST(CMMFDataBuffer*, aBuffer)->Data(); |
|
388 |
|
389 if (aLength>bufferDes.Length() || (aLength<0) || (aPosition<0)) |
|
390 User::Leave(KErrArgument); |
|
391 |
|
392 TInt sourceLength = aLength; |
|
393 TPtr8 bufferPtr(((sourceLength) ? &bufferDes[0] : NULL), sourceLength, sourceLength); |
|
394 TInt targetLength = iDes->MaxLength() - aPosition; |
|
395 if (targetLength>0 && sourceLength > 0) |
|
396 { |
|
397 if (sourceLength>targetLength) |
|
398 User::Leave(KErrOverflow); |
|
399 |
|
400 if ((iDes->Length() - aPosition) > 0) |
|
401 { |
|
402 TInt bytesToReplace = iDes->Length() - aPosition; |
|
403 if (sourceLength > bytesToReplace) |
|
404 { |
|
405 TPtrC8 replaceBuf = bufferPtr.Left(bytesToReplace); |
|
406 TPtrC8 appendBuf = bufferPtr.Right(sourceLength-bytesToReplace); |
|
407 iDes->Replace(aPosition, bytesToReplace, replaceBuf); |
|
408 iDes->Append(appendBuf); |
|
409 } |
|
410 else |
|
411 iDes->Replace(aPosition, sourceLength, bufferPtr); |
|
412 |
|
413 } |
|
414 else |
|
415 iDes->Append(bufferPtr.Ptr(),sourceLength); |
|
416 } |
|
417 else if (targetLength<0) |
|
418 User::Leave(KErrArgument); |
|
419 else if (aLength != 0) |
|
420 User::Leave(KErrOverflow); |
|
421 |
|
422 if (aSupplier) |
|
423 aSupplier->BufferEmptiedL(aBuffer); |
|
424 } |
|
425 else |
|
426 User::Leave(KErrNotSupported); |
|
427 } |
|
428 |
|
429 /** |
|
430 Empties aBuffer into iFile at specified location. Note that this is a synchronous write |
|
431 |
|
432 @param aBuffer |
|
433 The data buffer containing bytes to be written. |
|
434 @param aPosition |
|
435 The offset into file at which to start writing. |
|
436 */ |
|
437 void CMMFDescriptor::WriteBufferL( CMMFBuffer* aBuffer, TInt aPosition) |
|
438 { |
|
439 WriteBufferL( aBuffer, aPosition, NULL ); |
|
440 } |
|
441 |
|
442 /** |
|
443 Returns the amount of space available for the clip. |
|
444 |
|
445 @return The space available in descriptor (difference between length and maxlength). |
|
446 */ |
|
447 TInt64 CMMFDescriptor::BytesFree() |
|
448 { |
|
449 TInt64 length = iDes->Length() ; |
|
450 TInt64 maxLength = iDes->MaxLength() ; |
|
451 return( maxLength - length ) ; |
|
452 } |
|
453 |
|
454 /** |
|
455 Returns the length of the clip. |
|
456 |
|
457 @return The length (not max length) of the descriptor. |
|
458 */ |
|
459 TInt CMMFDescriptor::Size() |
|
460 { |
|
461 TInt length = iDes->Length(); |
|
462 return(length); |
|
463 } |
|
464 |
|
465 /** |
|
466 Returns the data type as a fourCC code for the CMMFDescriptor data source. |
|
467 |
|
468 @param aMediaId |
|
469 The ID of the media for which the codec is obtained. |
|
470 |
|
471 @return The data type fourCC code. |
|
472 */ |
|
473 TFourCC CMMFDescriptor::SourceDataTypeCode(TMediaId /*aMediaId*/) |
|
474 { |
|
475 return iSourceFourCC ; |
|
476 } |
|
477 |
|
478 /** |
|
479 Returns the data type as a fourCC code of the CMMFDescriptor data sink. |
|
480 |
|
481 Used by MDataSource and MDataSink. |
|
482 |
|
483 @return The data type fourCC code. |
|
484 */ |
|
485 TFourCC CMMFDescriptor::SinkDataTypeCode(TMediaId /*aMediaId*/) |
|
486 { |
|
487 return iSinkFourCC ; |
|
488 } |
|
489 |
|
490 /** |
|
491 CMMFDescriptor as a source is always passive so this function is not supported. |
|
492 |
|
493 @param aBuffer |
|
494 The emptied buffer. |
|
495 */ |
|
496 void CMMFDescriptor::BufferEmptiedL( CMMFBuffer* /*aBuffer*/ ) |
|
497 { |
|
498 Panic(EMMFDescriptorPanicBufferEmptiedLNotSupported); |
|
499 } |
|
500 |
|
501 /** |
|
502 Tests whether a source buffer can be created. |
|
503 |
|
504 @return A boolean indicating if the buffer can be created. EFalse if a CMMFDescriptor cannot create |
|
505 it's own buffer |
|
506 */ |
|
507 TBool CMMFDescriptor::CanCreateSourceBuffer() |
|
508 { |
|
509 return EFalse ; |
|
510 } |
|
511 |
|
512 /** |
|
513 Creates a source buffer. |
|
514 |
|
515 @param aMediaId |
|
516 The Media ID. |
|
517 @param aReference |
|
518 A boolean indicating if MDataSource owns the buffer. ETrue if MDataSource owns the buffer, |
|
519 EFalse if the caller owns the buffer. |
|
520 |
|
521 @return NULL as a CMMFFile cannot create it's own buffer |
|
522 */ |
|
523 CMMFBuffer* CMMFDescriptor::CreateSourceBufferL( TMediaId /*aMediaId*/, TBool& /*aReference*/ ) |
|
524 { |
|
525 User::Leave(KErrNotSupported); |
|
526 return NULL; |
|
527 } |
|
528 |
|
529 /** |
|
530 CMMFDescriptor as a sink is always passive so this function is not supported. |
|
531 |
|
532 @param aBuffer |
|
533 The filled buffer. |
|
534 */ |
|
535 void CMMFDescriptor::BufferFilledL( CMMFBuffer* /*aBuffer*/ ) |
|
536 { |
|
537 Panic(EMMFDescriptorPanicBufferFilledLNotSupported); |
|
538 } |
|
539 |
|
540 /** |
|
541 Tests whether a sink buffer can be created. |
|
542 |
|
543 @return A boolean indicating if the sink buffer can be created. EFalse if a CMMFDescriptor cannot |
|
544 create it's own buffer. |
|
545 */ |
|
546 TBool CMMFDescriptor::CanCreateSinkBuffer() |
|
547 { |
|
548 return EFalse ; |
|
549 } |
|
550 |
|
551 /** |
|
552 Creates a sink buffer. |
|
553 |
|
554 @param aMediaId |
|
555 The Media ID. |
|
556 @param aReference |
|
557 A boolean indicating if MDataSource owns the buffer. ETrue if MDataSource owns the buffer, |
|
558 EFalse if the caller owns the buffer. |
|
559 |
|
560 @return NULL as a CMMFDescriptor cannot create it's own buffer |
|
561 */ |
|
562 CMMFBuffer* CMMFDescriptor::CreateSinkBufferL( TMediaId /*aMediaId*/ , TBool& /*aReference*/) |
|
563 { |
|
564 User::Leave(KErrNotSupported); |
|
565 return NULL; |
|
566 } |