|
1 // Copyright (c) 2001-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 "BitmapTransformsPlugin.h" |
|
17 #include "BitmapConverter.h" |
|
18 #include <bitmtrans/bitmtranspanic.h> |
|
19 |
|
20 const TInt KLinesPerCall = 10; |
|
21 |
|
22 /** |
|
23 The function NewL constructs a CBitmapRotatorPlugin |
|
24 |
|
25 @returns CBitmapRotatorPlugin* |
|
26 |
|
27 |
|
28 */ |
|
29 |
|
30 MBitmapRotatorPlugin* CBitmapRotatorPlugin::NewL() |
|
31 { |
|
32 CBitmapRotatorPlugin* self = new(ELeave) CBitmapRotatorPlugin(); |
|
33 CleanupStack::PushL(self); |
|
34 self->ConstructL(); |
|
35 CleanupStack::Pop(self); |
|
36 return self; |
|
37 } |
|
38 |
|
39 /** |
|
40 Constructor for this class. Adds itself to <code>CActiveScheduler</code>. |
|
41 The priority of this active object is CActive::EPriorityIdle |
|
42 |
|
43 */ |
|
44 |
|
45 CBitmapRotatorPlugin::CBitmapRotatorPlugin() |
|
46 : CActive(CActive::EPriorityIdle), iScanlineDes(NULL,0) |
|
47 { |
|
48 CActiveScheduler::Add(this); |
|
49 } |
|
50 |
|
51 |
|
52 /** |
|
53 Performs second phase of contruction |
|
54 * |
|
55 */ |
|
56 |
|
57 void CBitmapRotatorPlugin::ConstructL() |
|
58 { |
|
59 } |
|
60 |
|
61 /** |
|
62 * |
|
63 * Default destructor for this class. |
|
64 * |
|
65 */ |
|
66 |
|
67 CBitmapRotatorPlugin::~CBitmapRotatorPlugin() |
|
68 { |
|
69 Cancel(); |
|
70 Cleanup(); |
|
71 |
|
72 // should have been deleted by cleanup |
|
73 ASSERT(iScanlineBuffer==NULL); |
|
74 ASSERT(iTempBitmap==NULL); |
|
75 ASSERT(iDevice==NULL); |
|
76 ASSERT(iGc==NULL); |
|
77 } |
|
78 |
|
79 |
|
80 /** |
|
81 This function performs deallocation of memory allocated by the class |
|
82 |
|
83 */ |
|
84 |
|
85 void CBitmapRotatorPlugin::Cleanup() |
|
86 { |
|
87 delete [] iScanlineBuffer; iScanlineBuffer = NULL; |
|
88 delete iTempBitmap; iTempBitmap = NULL; |
|
89 delete iGc; iGc = NULL; |
|
90 delete iDevice; iDevice = NULL; |
|
91 delete iScanlineBitmap; iScanlineBitmap = NULL; |
|
92 #if defined(ROTATION_PROFILING) |
|
93 TUint fcTaken=User::FastCounter() - iStartedAtFc; |
|
94 RDebug::Print(_L("BmpRotator: FC time taken %d"),fcTaken); |
|
95 #endif // |
|
96 } |
|
97 |
|
98 // MBitmapRotatorPlugin::Cancel() calls CActive::Cancel() |
|
99 void CBitmapRotatorPlugin::Cancel() |
|
100 { |
|
101 CActive::Cancel(); |
|
102 } |
|
103 |
|
104 /** |
|
105 The function Rotate schedules a rotate/mirror operation on a bitmap supplied in the |
|
106 aSrcBitmap whose output overwrites aSrcBitmap. |
|
107 Preconditions: |
|
108 aRequestStatus is not a NULL pointer |
|
109 aSrcBitmap is a fully constructed bitmap of unknown size including zero dimension |
|
110 aAngle is a member of the enumeration TRotationAngle |
|
111 |
|
112 @param "aRequestStatus" |
|
113 is a pointer to the completion status of the asynchronous operation. |
|
114 @param "CFbsBitmap& aBitmap" |
|
115 is a reference to a CFbsBitmap. This bitmap should have been created |
|
116 and is also an output |
|
117 @param "TRotationAngle aAngle" |
|
118 aAngle is a member of the enumeration TRotationAngle and specifies the rotation mirror operation |
|
119 |
|
120 @panic This function panics with TBitmapTransformsMain::ENoSourceBitmap when the aSrcBitmap has not been constructed |
|
121 ie its handle is 0 |
|
122 |
|
123 Sucess Guarantee |
|
124 aSrcBitmap contains the rotated bitmap |
|
125 aRequestStatus points to the value KErrorNone |
|
126 |
|
127 */ |
|
128 |
|
129 void CBitmapRotatorPlugin::Rotate(TRequestStatus* aRequestStatus, CFbsBitmap& aBitmap, TRotationAngle aAngle) |
|
130 { |
|
131 // [ panic if aRequestStatus is NULL ] |
|
132 __ASSERT_ALWAYS( (aRequestStatus != NULL), Panic( EBadArgumentScale ) ); |
|
133 |
|
134 //[ panic if the src has not been created] |
|
135 __ASSERT_ALWAYS( (aBitmap.Handle() != 0), Panic( ENoSourceBitmap ) ); |
|
136 |
|
137 //[ assert the angle is ok ] |
|
138 __ASSERT_ALWAYS( ( aAngle >= CBitmapRotator::ERotation90DegreesClockwise ) && |
|
139 ( aAngle <= CBitmapRotator::EMirrorVerticalAxis ), Panic(EBadArgumentRotate) ); |
|
140 |
|
141 ASSERT(iTempBitmap==NULL); |
|
142 |
|
143 iRotateStatus = aRequestStatus; |
|
144 *iRotateStatus = KRequestPending; |
|
145 |
|
146 if(aBitmap.ExtendedBitmapType()!=KNullUid) |
|
147 { |
|
148 RequestComplete(KErrNotSupported); |
|
149 return; |
|
150 } |
|
151 |
|
152 iTempBitmap = new CFbsBitmap; |
|
153 if (!iTempBitmap) |
|
154 { |
|
155 RequestComplete(KErrNoMemory); |
|
156 return; |
|
157 } |
|
158 Rotate(aRequestStatus, aBitmap, *iTempBitmap, aAngle); |
|
159 } |
|
160 |
|
161 /** |
|
162 The Rotate function schedules a rotate/mirror operation on a bitmap supplied in the srcBitmap and |
|
163 produces the output in the tgtBitmap. |
|
164 The CBitmapRotatorPlugin is an active object and as such provides asynchronous operations |
|
165 |
|
166 Preconditions: |
|
167 aRequestStatus is not a NULL pointer |
|
168 aSrcBitmap is a fully constructed bitmap of unknown size including zero dimension and |
|
169 of type EColor16M |
|
170 aTgtBitmap is a fully constructed bitmap of unknown size including zero dimension |
|
171 and is of type EColor16M |
|
172 aAngle is a member of the enumeration TRotationAngle |
|
173 |
|
174 Sucess Guarantee: |
|
175 aTgtBitmap contains the rotated bitmap |
|
176 aRequestStatus points to the value KErrNone |
|
177 |
|
178 Minimal Guarantee: |
|
179 The bitmap supplied in aSrcBitmap is unaltered |
|
180 |
|
181 |
|
182 @param "TRequestStatus* aRequestStatus" |
|
183 a pointer to the completion status of the asynchronous operation. |
|
184 @param "CFbsBitmap& aSrcBitmap" |
|
185 This bitmap should have been created and be of type EColor16M |
|
186 @param "CFbsBitmap& aTgtBitmap" |
|
187 This bitmap should have been created and be of type EColor16M |
|
188 @param "TRotationAngle aAngle" |
|
189 is a member of the enumeration TRotationAngle and specifies the rotation mirror operation |
|
190 |
|
191 |
|
192 @panic This function panics with TBitmapTransformsMain::ENoSourceBitmap when the aSrcBitmap has not been constructed |
|
193 i.e. its handle is zero |
|
194 |
|
195 |
|
196 */ |
|
197 |
|
198 void CBitmapRotatorPlugin::Rotate(TRequestStatus* aRequestStatus, CFbsBitmap& aSrcBitmap, CFbsBitmap& aTgtBitmap, TRotationAngle aAngle) |
|
199 { |
|
200 // [ panic if aRequestStatus is NULL ] |
|
201 __ASSERT_ALWAYS( (aRequestStatus != NULL), Panic( EBadArgumentScale ) ); |
|
202 |
|
203 //[ panic if the src has not been created] |
|
204 __ASSERT_ALWAYS( (aSrcBitmap.Handle() != 0), Panic( ENoSourceBitmap ) ); |
|
205 |
|
206 //[ assert the angle is ok ] |
|
207 __ASSERT_ALWAYS( ( aAngle >= CBitmapRotator::ERotation90DegreesClockwise ) && |
|
208 ( aAngle <= CBitmapRotator::EMirrorVerticalAxis ), Panic(EBadArgumentRotate) ); |
|
209 |
|
210 //[ we do not need to ensure a tgt has been created] |
|
211 #if defined(ROTATION_PROFILING) |
|
212 iStartedAtFc = User::FastCounter(); |
|
213 #endif // ROTATION_PROFILING |
|
214 // Initialize member variables |
|
215 iSrcBitmap = &aSrcBitmap; |
|
216 iTgtBitmap = &aTgtBitmap; |
|
217 iAngle = aAngle; |
|
218 iCurOffset = 0; |
|
219 iBitmapSize = iSrcBitmap->SizeInPixels(); |
|
220 iDisplayMode = iSrcBitmap->DisplayMode(); |
|
221 iRotateStatus = aRequestStatus; |
|
222 *iRotateStatus = KRequestPending; |
|
223 |
|
224 if(aSrcBitmap.ExtendedBitmapType()!=KNullUid) |
|
225 { |
|
226 RequestComplete(KErrNotSupported); |
|
227 return; |
|
228 } |
|
229 |
|
230 if(aTgtBitmap.Handle()!=0 && aTgtBitmap.ExtendedBitmapType()!=KNullUid) |
|
231 { |
|
232 RequestComplete(KErrNotSupported); |
|
233 return; |
|
234 } |
|
235 |
|
236 TSize newSize; |
|
237 if ((aAngle == CBitmapRotator::ERotation90DegreesClockwise) || (aAngle == CBitmapRotator::ERotation270DegreesClockwise)) |
|
238 { |
|
239 newSize.SetSize(iBitmapSize.iHeight, iBitmapSize.iWidth); // Swap width and height |
|
240 } |
|
241 else |
|
242 { |
|
243 newSize.SetSize(iBitmapSize.iWidth, iBitmapSize.iHeight); |
|
244 } |
|
245 TInt err = iTgtBitmap->Create(newSize, iDisplayMode); |
|
246 |
|
247 TBool bmpDeviceNeeded=EFalse; |
|
248 if (iSrcBitmap->DisplayMode()==EColor16M || iSrcBitmap->DisplayMode()==EColor16MU || |
|
249 iSrcBitmap->DisplayMode()==EColor16MA || |
|
250 iSrcBitmap->DisplayMode()==EColor256 || iSrcBitmap->DisplayMode()==EGray256 || |
|
251 iSrcBitmap->DisplayMode()==EColor64K ) |
|
252 { |
|
253 iScanlineDisplayMode = iSrcBitmap->DisplayMode(); |
|
254 } |
|
255 else |
|
256 { |
|
257 // we can't cope with that color mode, then use the highest one for intermediate buffer |
|
258 bmpDeviceNeeded = ETrue; |
|
259 iScanlineDisplayMode= EColor16MA; |
|
260 } |
|
261 iPixelSizeInBytes = TDisplayModeUtils::NumDisplayModeBitsPerPixel(iScanlineDisplayMode) / 8; |
|
262 |
|
263 TInt scanlineLength=iSrcBitmap->ScanLineLength(newSize.iWidth, iScanlineDisplayMode); |
|
264 scanlineLength=Align4(scanlineLength); |
|
265 if (err == KErrNone) |
|
266 { |
|
267 ASSERT(iScanlineBuffer==NULL); |
|
268 iScanlineBuffer = new TUint32 [ scanlineLength ]; |
|
269 if(!iScanlineBuffer) |
|
270 { |
|
271 err = KErrNoMemory; |
|
272 } |
|
273 } |
|
274 if (err != KErrNone) |
|
275 { |
|
276 Cleanup(); |
|
277 RequestComplete(err); |
|
278 return; |
|
279 } |
|
280 iRows = newSize.iHeight; |
|
281 |
|
282 TPtr8 scanlineDes(reinterpret_cast<TText8*>(iScanlineBuffer),scanlineLength,scanlineLength); // Use a temporary to avoid compiler warnings |
|
283 iScanlineDes.Set(scanlineDes); |
|
284 |
|
285 ASSERT(iDevice==NULL); |
|
286 if (bmpDeviceNeeded) |
|
287 { |
|
288 iScanlineBitmap = new CFbsBitmap(); |
|
289 err= (iScanlineBitmap? iScanlineBitmap->Create(TSize(iTgtBitmap->SizeInPixels().iWidth, 1), iScanlineDisplayMode) |
|
290 : KErrNoMemory); |
|
291 if (err==KErrNone) |
|
292 { |
|
293 TRAP(err, iDevice = CFbsBitmapDevice::NewL(iTgtBitmap)); |
|
294 } |
|
295 if (err == KErrNone) |
|
296 { |
|
297 err = iDevice->CreateContext(iGc); |
|
298 } |
|
299 } |
|
300 |
|
301 if (err != KErrNone) |
|
302 { |
|
303 Cleanup(); |
|
304 RequestComplete(err); |
|
305 return; |
|
306 } |
|
307 |
|
308 // Start the active object |
|
309 SelfComplete(KErrNone); |
|
310 } |
|
311 |
|
312 /** |
|
313 This function is called by the Active Scheduler |
|
314 to perform the rotate operation |
|
315 |
|
316 */ |
|
317 |
|
318 void CBitmapRotatorPlugin::DoRotate() |
|
319 { |
|
320 TInt linesLeftPerCall = KLinesPerCall; |
|
321 while ((linesLeftPerCall > 0) && (iCurOffset < iRows)) |
|
322 { |
|
323 switch (iAngle) |
|
324 { |
|
325 // Rotation of 90 degrees |
|
326 case CBitmapRotator::ERotation90DegreesClockwise: |
|
327 { |
|
328 iSrcBitmap->GetVerticalScanLine(iScanlineDes, iCurOffset, iScanlineDisplayMode); |
|
329 FlipScanLine(iScanlineDes, iTgtBitmap->SizeInPixels().iWidth); |
|
330 PutScanline(iCurOffset); |
|
331 break; |
|
332 } |
|
333 |
|
334 // Rotation of 180 degrees |
|
335 case CBitmapRotator::ERotation180DegreesClockwise: |
|
336 { |
|
337 iSrcBitmap->GetScanLine(iScanlineDes,TPoint(0, iCurOffset), iBitmapSize.iWidth, iScanlineDisplayMode); |
|
338 FlipScanLine(iScanlineDes, iBitmapSize.iWidth); |
|
339 PutScanline(iBitmapSize.iHeight - 1 - iCurOffset); |
|
340 break; |
|
341 } |
|
342 |
|
343 // Rotation of 270 degrees |
|
344 case CBitmapRotator::ERotation270DegreesClockwise: |
|
345 { |
|
346 iSrcBitmap->GetVerticalScanLine(iScanlineDes, iCurOffset, iScanlineDisplayMode); |
|
347 PutScanline(iBitmapSize.iWidth - 1 - iCurOffset); |
|
348 break; |
|
349 } |
|
350 |
|
351 // Flip about the vertical Axis |
|
352 case CBitmapRotator::EMirrorVerticalAxis: |
|
353 { |
|
354 iSrcBitmap->GetScanLine(iScanlineDes,TPoint(0,iCurOffset),iBitmapSize.iWidth,iScanlineDisplayMode); |
|
355 FlipScanLine(iScanlineDes, iBitmapSize.iWidth); |
|
356 PutScanline(iCurOffset); |
|
357 break; |
|
358 } |
|
359 |
|
360 // Flip about the horizontal axis |
|
361 case CBitmapRotator::EMirrorHorizontalAxis: |
|
362 { |
|
363 iSrcBitmap->GetScanLine(iScanlineDes,TPoint(0,iCurOffset),iBitmapSize.iWidth,iScanlineDisplayMode); |
|
364 PutScanline(iBitmapSize.iHeight-1-iCurOffset); |
|
365 break; |
|
366 } |
|
367 |
|
368 default: |
|
369 { |
|
370 ASSERT( EFalse ); |
|
371 } |
|
372 } |
|
373 |
|
374 iCurOffset++; |
|
375 linesLeftPerCall--; |
|
376 } |
|
377 |
|
378 if (iCurOffset == iRows) |
|
379 { |
|
380 TInt duplicateErr = KErrNone; |
|
381 if (iTempBitmap) |
|
382 { |
|
383 duplicateErr = iSrcBitmap->Duplicate(iTgtBitmap->Handle()); |
|
384 } |
|
385 Cleanup(); |
|
386 RequestComplete(duplicateErr); |
|
387 } |
|
388 else |
|
389 { |
|
390 // Start the active object |
|
391 SelfComplete(KErrNone); |
|
392 } |
|
393 } |
|
394 |
|
395 /** |
|
396 Handles an active object’s request completion event. |
|
397 The function is called by the active scheduler |
|
398 when a request completion event occurs, |
|
399 |
|
400 */ |
|
401 |
|
402 void CBitmapRotatorPlugin::RunL() |
|
403 { |
|
404 DoRotate(); |
|
405 } |
|
406 |
|
407 /** |
|
408 Implements cancellation of an outstanding request. |
|
409 This function is called as part of the active object’s Cancel(). |
|
410 It must call the appropriate cancel function offered by the active object’s asynchronous service provider. |
|
411 The asynchronous service provider’s cancel is expected to act immediately. |
|
412 |
|
413 */ |
|
414 |
|
415 void CBitmapRotatorPlugin::DoCancel() |
|
416 { |
|
417 Cleanup(); |
|
418 RequestComplete(KErrCancel); |
|
419 } |
|
420 |
|
421 /** |
|
422 Signals to the current thread that the asynchronous request |
|
423 associated with the request status is complete. |
|
424 @param aReason is a TInt and is the completion code of this request. |
|
425 |
|
426 */ |
|
427 |
|
428 void CBitmapRotatorPlugin::RequestComplete(TInt aReason) |
|
429 { |
|
430 ASSERT(iRotateStatus); |
|
431 TRequestStatus* status = iRotateStatus; |
|
432 User::RequestComplete(status, aReason); |
|
433 } |
|
434 |
|
435 /** |
|
436 This function activates the active object and |
|
437 signals completion of the current asynchronous operation |
|
438 |
|
439 */ |
|
440 |
|
441 void CBitmapRotatorPlugin::SelfComplete(TInt aReason) |
|
442 { |
|
443 SetActive(); |
|
444 TRequestStatus* status = &iStatus; |
|
445 User::RequestComplete(status, aReason); |
|
446 } |
|
447 |
|
448 /** |
|
449 template function that can be used for swapping of memory locations |
|
450 of particular pointer type |
|
451 @param ptr1 - pointer to value1 |
|
452 @param ptr2 - pointer to value2 |
|
453 */ |
|
454 template <class T> |
|
455 inline void SwapPixels(T* ptr1, T* ptr2) |
|
456 { |
|
457 T temp = *ptr1; |
|
458 *ptr1 = *ptr2; |
|
459 *ptr2 = temp; |
|
460 } |
|
461 |
|
462 /** |
|
463 template function that can be used for mirroring of linear |
|
464 memory location of a particular scalar type |
|
465 @param aScanLinePtr location address |
|
466 @param aWidth width of location in elements, not bytes |
|
467 */ |
|
468 template <class T> |
|
469 inline void FlipLine(TUint8* aScanLinePtr, TInt aWidth) |
|
470 { |
|
471 T* startPixelPtr = reinterpret_cast<T*>(aScanLinePtr); |
|
472 T* endPixelPtr = startPixelPtr + aWidth - 1; |
|
473 if (aWidth&1) |
|
474 { |
|
475 SwapPixels(startPixelPtr++, endPixelPtr--); |
|
476 } |
|
477 if(aWidth&3) |
|
478 { |
|
479 while (startPixelPtr < endPixelPtr) |
|
480 { |
|
481 SwapPixels(startPixelPtr++, endPixelPtr--); |
|
482 } |
|
483 } |
|
484 else |
|
485 { |
|
486 while (startPixelPtr < endPixelPtr) |
|
487 { |
|
488 SwapPixels(startPixelPtr++, endPixelPtr--); |
|
489 SwapPixels(startPixelPtr++, endPixelPtr--); |
|
490 } |
|
491 } |
|
492 } |
|
493 |
|
494 /** |
|
495 This function flips a scan line buffer of width aWidth |
|
496 PreConditions: |
|
497 aWidth >= 0 && aWidth is the length of the buffer |
|
498 aDes is a reference to a buffer of rgb pixels |
|
499 Postcondition: |
|
500 The contents of the buffer have flipped about the buffers centre |
|
501 |
|
502 @param TDes8 aDes |
|
503 reference to a buffer of rgb pixels of lenth aWidth |
|
504 @param Tint aWidth |
|
505 is the width of the buffer |
|
506 |
|
507 */ |
|
508 void CBitmapRotatorPlugin::FlipScanLine(TDes8& aDes, TInt aWidth) |
|
509 { |
|
510 //[ assert consistency between descriptor length and width ] |
|
511 ASSERT( (aDes.Length() == (iPixelSizeInBytes * aWidth) )); |
|
512 |
|
513 TUint8* const scanLinePtr=const_cast<TUint8*>(aDes.Ptr()); |
|
514 |
|
515 switch (iPixelSizeInBytes) |
|
516 { |
|
517 case 4: |
|
518 { |
|
519 FlipLine<TUint32>(scanLinePtr, aWidth); |
|
520 } |
|
521 break; |
|
522 case 3: |
|
523 { |
|
524 TUint8* startPixelPtr = scanLinePtr; |
|
525 TUint8* endPixelPtr = startPixelPtr + (aWidth - 1)*iPixelSizeInBytes; |
|
526 while (startPixelPtr < endPixelPtr) |
|
527 { |
|
528 TUint8 temp0 = startPixelPtr[0]; |
|
529 TUint8 temp1 = startPixelPtr[1]; |
|
530 TUint8 temp2 = startPixelPtr[2]; |
|
531 startPixelPtr[0] = endPixelPtr[0]; |
|
532 startPixelPtr[1] = endPixelPtr[1]; |
|
533 startPixelPtr[2] = endPixelPtr[2]; |
|
534 endPixelPtr[0] = temp0; |
|
535 endPixelPtr[1] = temp1; |
|
536 endPixelPtr[2] = temp2; |
|
537 startPixelPtr += iPixelSizeInBytes; |
|
538 endPixelPtr -= iPixelSizeInBytes; |
|
539 } |
|
540 } |
|
541 break; |
|
542 case 2: |
|
543 { |
|
544 FlipLine<TUint16>(scanLinePtr, aWidth); |
|
545 } |
|
546 break; |
|
547 case 1: |
|
548 { |
|
549 FlipLine<TUint8>(scanLinePtr, aWidth); |
|
550 } |
|
551 break; |
|
552 |
|
553 default: |
|
554 ASSERT(EFalse); |
|
555 } |
|
556 } |
|
557 |
|
558 void CBitmapRotatorPlugin::PutScanline(TInt aYPos) |
|
559 { |
|
560 if (iScanlineBitmap) |
|
561 { |
|
562 iScanlineBitmap->SetScanLine(iScanlineDes, 0); |
|
563 iGc->BitBlt(TPoint(0, aYPos), iScanlineBitmap); |
|
564 } |
|
565 else |
|
566 { |
|
567 iTgtBitmap->SetScanLine(iScanlineDes, aYPos); |
|
568 } |
|
569 } |
|
570 |
|
571 /* |
|
572 * |
|
573 * CustomCommand |
|
574 * @param aUid |
|
575 * @param aParam |
|
576 * @return 'TInt' an error code indicating success or failure of the |
|
577 * command |
|
578 * |
|
579 */ |
|
580 TInt CBitmapRotatorPlugin::CustomCommand(TUid /*aUid*/, TAny* /*aParam*/) |
|
581 { |
|
582 TInt status = KErrNotSupported; |
|
583 return status; |
|
584 } |