|
1 /* |
|
2 * Copyright (c) 2007 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: Incremental OpenL() utility |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 #include <e32base.h> |
|
20 #include <mpxmessage.h> |
|
21 #include <mpxcollectionpath.h> |
|
22 #include <mpxcollectionutility.h> |
|
23 #include <mpxcollectionmessagedefs.h> |
|
24 #include <mpxmessagegeneraldefs.h> |
|
25 #include <mpxmediageneraldefs.h> |
|
26 #include <mpxcommandgeneraldefs.h> |
|
27 #include <mpxincrementalopendefs.h> |
|
28 #include <mpxmediacontainerdefs.h> |
|
29 #include <mpxcollectionmessage.h> |
|
30 #include <mpxlog.h> |
|
31 #include <mpxcollectionopenlresultdef.h> |
|
32 #include <mpxcollectioncommanddefs.h> |
|
33 #include "mpxcollectionopenutility.h" |
|
34 #include <e32math.h> |
|
35 |
|
36 // CONSTANTS |
|
37 const TInt KArrayGranularity = 5; |
|
38 |
|
39 // --------------------------------------------------------------------------- |
|
40 // static function to compare two datablock items |
|
41 // used for sorting datablocks |
|
42 // --------------------------------------------------------------------------- |
|
43 // |
|
44 static TInt CompareAsc( const TMPXOpenDataBlock& aFirst, |
|
45 const TMPXOpenDataBlock& aSecond ) |
|
46 { |
|
47 return aFirst.iOffset > aSecond.iOffset; |
|
48 } |
|
49 |
|
50 // --------------------------------------------------------------------------- |
|
51 // static function to compare two datablock items |
|
52 // used for sorting datablocks |
|
53 // --------------------------------------------------------------------------- |
|
54 // |
|
55 static TInt CompareDsc( const TMPXOpenDataBlock& aFirst, |
|
56 const TMPXOpenDataBlock& aSecond ) |
|
57 { |
|
58 return aFirst.iOffset < aSecond.iOffset; |
|
59 } |
|
60 |
|
61 // --------------------------------------------------------------------------- |
|
62 // Constructor |
|
63 // --------------------------------------------------------------------------- |
|
64 // |
|
65 CMPXCollectionOpenUtility::CMPXCollectionOpenUtility( MMPXCollectionObserver* aObs, |
|
66 TUid aMode ) |
|
67 : iFetchStep(EFetchNone), |
|
68 iObs( aObs ), |
|
69 iIncrementalChunks(KArrayGranularity), |
|
70 iMode( aMode ) |
|
71 |
|
72 { |
|
73 } |
|
74 |
|
75 |
|
76 // --------------------------------------------------------------------------- |
|
77 // 2nd Phase Constructor |
|
78 // --------------------------------------------------------------------------- |
|
79 // |
|
80 void CMPXCollectionOpenUtility::ConstructL() |
|
81 { |
|
82 iTimer = CPeriodic::NewL( CActive::EPriorityStandard ); |
|
83 } |
|
84 |
|
85 |
|
86 // --------------------------------------------------------------------------- |
|
87 // Two-Phased Constructor |
|
88 // --------------------------------------------------------------------------- |
|
89 // |
|
90 EXPORT_C CMPXCollectionOpenUtility* CMPXCollectionOpenUtility::NewL( |
|
91 MMPXCollectionObserver* aObs, |
|
92 TUid aMode ) |
|
93 { |
|
94 CMPXCollectionOpenUtility* self = |
|
95 new( ELeave ) CMPXCollectionOpenUtility( aObs, aMode ); |
|
96 CleanupStack::PushL( self ); |
|
97 self->ConstructL(); |
|
98 CleanupStack::Pop( self ); |
|
99 return self; |
|
100 } |
|
101 |
|
102 // --------------------------------------------------------------------------- |
|
103 // Destructor |
|
104 // --------------------------------------------------------------------------- |
|
105 // |
|
106 CMPXCollectionOpenUtility::~CMPXCollectionOpenUtility() |
|
107 { |
|
108 if( iCollection ) |
|
109 { |
|
110 iCollection->Close(); |
|
111 } |
|
112 |
|
113 if( iTimer ) |
|
114 { |
|
115 iTimer->Cancel(); |
|
116 delete iTimer; |
|
117 } |
|
118 |
|
119 iIncrementalChunks.Close(); |
|
120 delete iPath; |
|
121 delete iMedia; |
|
122 } |
|
123 |
|
124 // --------------------------------------------------------------------------- |
|
125 // Start the incremental fetching operation |
|
126 // --------------------------------------------------------------------------- |
|
127 // |
|
128 EXPORT_C void CMPXCollectionOpenUtility::StartL( TArray<TMPXAttribute> /*aAttrs*/, |
|
129 TInt aChunkSize, |
|
130 TInt aOffset, |
|
131 TDirection aDirection, |
|
132 TMPXAttribute aKeyAttribute ) |
|
133 { |
|
134 // Assert we are idle |
|
135 ASSERT( iFetchStep == EFetchNone ); |
|
136 MPX_DEBUG1("CMPXCollectionOpenUtility::StartL <---"); |
|
137 // Copy the operation data |
|
138 iFetchInfo.iSize = aChunkSize; |
|
139 iFetchInfo.iOffset = aOffset; |
|
140 iFetchDirection = aDirection; |
|
141 iKeyAttribute = aKeyAttribute; |
|
142 iData = NULL; |
|
143 delete iMedia; |
|
144 iMedia = NULL; |
|
145 delete iPath; |
|
146 iPath = NULL; |
|
147 // Start reading |
|
148 iFetchStep = EFetchCount; |
|
149 RunNext(); |
|
150 MPX_DEBUG1("CMPXCollectionOpenUtility::StartL --->"); |
|
151 } |
|
152 |
|
153 // --------------------------------------------------------------------------- |
|
154 // Start the incremental fetching operation |
|
155 // --------------------------------------------------------------------------- |
|
156 // |
|
157 EXPORT_C void CMPXCollectionOpenUtility::StartL( const CMPXCollectionPath& aPath, |
|
158 TArray<TMPXAttribute> /*aAttrs*/, |
|
159 TInt aChunkSize, |
|
160 TInt aOffset, |
|
161 TDirection aDirection, |
|
162 TMPXAttribute aKeyAttribute ) |
|
163 { |
|
164 // Assert we are idle and isolated mode |
|
165 MPX_ASSERT( iFetchStep == EFetchNone ); |
|
166 MPX_ASSERT( iMode == KMcModeIsolated || iMode == KMcModePlaylist ); |
|
167 MPX_DEBUG1("CMPXCollectionOpenUtility::StartL aPath <---"); |
|
168 if( !iCollection ) |
|
169 { |
|
170 iCollection = MMPXCollectionUtility::NewL( this, iMode ); |
|
171 } |
|
172 |
|
173 // Copy the operation data |
|
174 MPX_DEBUG_PATH( aPath ); |
|
175 iFetchInfo.iSize = aChunkSize; |
|
176 iFetchInfo.iOffset = aOffset; |
|
177 iFetchDirection = aDirection; |
|
178 iKeyAttribute = aKeyAttribute; |
|
179 iData = NULL; |
|
180 delete iMedia; |
|
181 iMedia = NULL; |
|
182 |
|
183 delete iPath; |
|
184 iPath = NULL; |
|
185 iPath = CMPXCollectionPath::NewL( aPath ); |
|
186 |
|
187 // Start the fetch operation by setting up the context |
|
188 // to the correct path |
|
189 // |
|
190 iFetchStep = EFetchPath; |
|
191 RunNext(); |
|
192 |
|
193 MPX_DEBUG1("CMPXCollectionOpenUtility::StartL --->"); |
|
194 } |
|
195 |
|
196 // --------------------------------------------------------------------------- |
|
197 // Stop the incremental fetching operation |
|
198 // --------------------------------------------------------------------------- |
|
199 // |
|
200 EXPORT_C void CMPXCollectionOpenUtility::Stop() |
|
201 { |
|
202 // Cancel all outstanding collection open requests |
|
203 MPX_DEBUG1("CMPXCollectionOpenUtility::Stop <---"); |
|
204 if( iCollection ) |
|
205 { |
|
206 iCollection->Collection().CancelRequest(); |
|
207 } |
|
208 iTimer->Cancel(); |
|
209 iIncrementalChunks.Reset(); |
|
210 delete iMedia; |
|
211 iMedia = NULL; |
|
212 iData = NULL; |
|
213 iFetchStep = EFetchNone; |
|
214 MPX_DEBUG1("CMPXCollectionOpenUtility::Stop --->"); |
|
215 } |
|
216 |
|
217 // --------------------------------------------------------------------------- |
|
218 // Set the direction of the incremental fetching algorithm |
|
219 // --------------------------------------------------------------------------- |
|
220 // |
|
221 EXPORT_C void CMPXCollectionOpenUtility::SetDirection( TDirection aDirection ) |
|
222 { |
|
223 iFetchDirection = aDirection; |
|
224 |
|
225 if( iFetchStep == EFetchItems || iFetchStep == EFetchCommand ) |
|
226 { |
|
227 TBool skipFirst = iFetchStep == EFetchCommand ? ETrue : EFalse; |
|
228 |
|
229 if( iFetchDirection == EFetchDown ) |
|
230 { |
|
231 DoSortAscend( skipFirst ); |
|
232 } |
|
233 else if( iFetchDirection == EFetchUp ) |
|
234 { |
|
235 DoSortDescend( skipFirst ); |
|
236 } |
|
237 else if( iFetchDirection == EFetchNormal ) |
|
238 { |
|
239 TRAP_IGNORE( DoSortNormalL( skipFirst ) ); |
|
240 } |
|
241 } |
|
242 } |
|
243 |
|
244 // --------------------------------------------------------------------------- |
|
245 // Set the fetching delay |
|
246 // --------------------------------------------------------------------------- |
|
247 // |
|
248 EXPORT_C void CMPXCollectionOpenUtility::SetDelay( TInt aDelay ) |
|
249 { |
|
250 iFetchDelay = aDelay; |
|
251 } |
|
252 |
|
253 // --------------------------------------------------------------------------- |
|
254 // Get the current path |
|
255 // --------------------------------------------------------------------------- |
|
256 // |
|
257 EXPORT_C CMPXCollectionPath* CMPXCollectionOpenUtility::PathL() |
|
258 { |
|
259 CMPXCollectionPath* p(NULL); |
|
260 |
|
261 if( iCollection ) |
|
262 { |
|
263 p = iCollection->Collection().PathL(); |
|
264 } |
|
265 return p; |
|
266 } |
|
267 |
|
268 // --------------------------------------------------------------------------- |
|
269 // Handle Collection Message |
|
270 // --------------------------------------------------------------------------- |
|
271 // |
|
272 void CMPXCollectionOpenUtility::HandleCollectionMessage(CMPXMessage* aMsg, TInt aErr) |
|
273 { |
|
274 if( aErr == KErrNone && aMsg ) |
|
275 { |
|
276 TRAP_IGNORE( DoHandleCollectionMessageL( *aMsg ) ); |
|
277 } |
|
278 } |
|
279 |
|
280 // --------------------------------------------------------------------------- |
|
281 // HandleOpenL |
|
282 // --------------------------------------------------------------------------- |
|
283 // |
|
284 void CMPXCollectionOpenUtility::HandleOpenL(const CMPXMedia& aEntries, |
|
285 TInt aIndex, |
|
286 TBool aComplete, |
|
287 TInt aError) |
|
288 { |
|
289 if( iFetchStep == EFetchCount ) |
|
290 { |
|
291 DoHandleCountL( aEntries, aIndex, aError ); |
|
292 } |
|
293 else if( iFetchStep == EFetchItems ) |
|
294 { |
|
295 DoHandleFetchItemsL( aEntries, aIndex, aError ); |
|
296 } |
|
297 else |
|
298 { |
|
299 MPX_DEBUG1("CMPXCollectionOpenUtility::HandleOpenL EFetchPath/EFetchNone"); |
|
300 iFetchStep = EFetchNone; |
|
301 iObs->HandleOpenL( aEntries, aIndex, aComplete, aError ); |
|
302 } |
|
303 } |
|
304 |
|
305 // --------------------------------------------------------------------------- |
|
306 // HandleOpenL |
|
307 // --------------------------------------------------------------------------- |
|
308 // |
|
309 void CMPXCollectionOpenUtility::HandleOpenL(const CMPXCollectionPlaylist& aPlaylist, |
|
310 TInt aError) |
|
311 { |
|
312 iObs->HandleOpenL( aPlaylist, aError ); |
|
313 } |
|
314 |
|
315 // --------------------------------------------------------------------------- |
|
316 // Handle Command Complete |
|
317 // --------------------------------------------------------------------------- |
|
318 // |
|
319 void CMPXCollectionOpenUtility::HandleCommandComplete(CMPXCommand* aCommandResult, |
|
320 TInt aError ) |
|
321 { |
|
322 // Continue fetching items |
|
323 iFetchStep = EFetchItems; |
|
324 TRAP_IGNORE( DoHandleCommandCompleteL( *aCommandResult, aError ) ); |
|
325 } |
|
326 |
|
327 // --------------------------------------------------------------------------- |
|
328 // Handle Collection Media |
|
329 // --------------------------------------------------------------------------- |
|
330 // |
|
331 void CMPXCollectionOpenUtility::HandleCollectionMediaL(const CMPXMedia& /*aMedia*/, |
|
332 TInt /*aError*/) |
|
333 { |
|
334 // Do Nothing |
|
335 } |
|
336 |
|
337 // --------------------------------------------------------------------------- |
|
338 // Handle Collection Messages |
|
339 // --------------------------------------------------------------------------- |
|
340 // |
|
341 void CMPXCollectionOpenUtility::DoHandleCollectionMessageL( const CMPXMessage& aMsg ) |
|
342 { |
|
343 TMPXMessageId id( aMsg.ValueTObjectL<TMPXMessageId>( KMPXMessageGeneralId ) ); |
|
344 if ( KMPXMessageGeneral == id && |
|
345 iFetchStep == EFetchPath ) |
|
346 { |
|
347 TInt event( aMsg.ValueTObjectL<TInt>( KMPXMessageGeneralEvent ) ); |
|
348 TInt type( aMsg.ValueTObjectL<TInt>( KMPXMessageGeneralType ) ); |
|
349 TInt data( aMsg.ValueTObjectL<TInt>( KMPXMessageGeneralData) ); |
|
350 if ( event == TMPXCollectionMessage::EPathChanged && |
|
351 type == EMcPathChangedByOpen ) |
|
352 { |
|
353 MPX_DEBUG1("CMPXCollectionOpenUtility::DoHandleCollectionMessageL -- path opened"); |
|
354 |
|
355 if( data == EMcContainerOpened) |
|
356 { |
|
357 iFetchStep = EFetchCount; |
|
358 RunNext(); |
|
359 } |
|
360 else if( data == EMcItemOpened ) // only 2 cases |
|
361 { |
|
362 // Playlist, simply forward back to the observer |
|
363 iCollection->Collection().OpenL(); |
|
364 iFetchStep = EFetchNone; |
|
365 } |
|
366 } |
|
367 } |
|
368 } |
|
369 |
|
370 // --------------------------------------------------------------------------- |
|
371 // Handle Command complete |
|
372 // --------------------------------------------------------------------------- |
|
373 // |
|
374 void CMPXCollectionOpenUtility::DoHandleCommandCompleteL(CMPXCommand& /*aCommandResult*/, |
|
375 TInt aError) |
|
376 { |
|
377 if( iSelecting ) |
|
378 { |
|
379 iSelecting = EFalse; |
|
380 } |
|
381 else if( aError == KErrNone ) |
|
382 { |
|
383 // Get the data to return to the client, callback at HandleOpen() |
|
384 // |
|
385 // Implemented because the command tells the plugin to fetch the |
|
386 // next block of data. However, the actual media object containing |
|
387 // the current browse data may have been re-allocated. We cannot |
|
388 // assume that the data pointer remains the same. Therefore, it is |
|
389 // safer to refetch the data from the collection via OpenL() |
|
390 // This call should be FAST because the data has already been read at this point |
|
391 // |
|
392 MPX_DEBUG1("CMPXCollectionOpenUtility::HandleCommandComplete OpenL <---"); |
|
393 if( iIncrementalChunks.Count() == 1 || iFirstOpen ) |
|
394 { |
|
395 DoSelectIndexL(); |
|
396 } |
|
397 iCollection->Collection().OpenL(); |
|
398 } |
|
399 else if( aError == KErrNotReady ) |
|
400 { |
|
401 // Cache was deleted, need to restart the fetching operation |
|
402 Stop(); |
|
403 iFetchStep = EFetchCount; |
|
404 iCollection->Collection().OpenL(); |
|
405 } |
|
406 else // aError != KErrNone |
|
407 { |
|
408 // Error occured, such as not supported |
|
409 MPX_DEBUG2("CMPXCollectionOpenUtility::HandleCommandComplete Error %i <---", aError); |
|
410 iFetchStep = EFetchNone; |
|
411 |
|
412 CMPXMedia* temp = CMPXMedia::NewL(); |
|
413 CleanupStack::PushL( temp ); |
|
414 iObs->HandleOpenL( *temp, 0, ETrue, aError ); |
|
415 CleanupStack::PopAndDestroy( temp ); |
|
416 } |
|
417 } |
|
418 |
|
419 // --------------------------------------------------------------------------- |
|
420 // Fetch count step |
|
421 // --------------------------------------------------------------------------- |
|
422 // |
|
423 void CMPXCollectionOpenUtility::DoFetchCountL() |
|
424 { |
|
425 if( !iCollection ) |
|
426 { |
|
427 iCollection = MMPXCollectionUtility::NewL( this, iMode ); |
|
428 } |
|
429 |
|
430 // Ask for the total item count |
|
431 // Cache current iPath |
|
432 delete iPath; |
|
433 iPath = NULL; |
|
434 iPath = iCollection->Collection().PathL(); |
|
435 |
|
436 iCollection->Collection().OpenL(); |
|
437 } |
|
438 |
|
439 // --------------------------------------------------------------------------- |
|
440 // Handle the count step |
|
441 // --------------------------------------------------------------------------- |
|
442 // |
|
443 void CMPXCollectionOpenUtility::DoHandleCountL(const CMPXMedia& aEntries, |
|
444 TInt aIndex, |
|
445 TInt aError) |
|
446 { |
|
447 ASSERT( iFetchStep == EFetchCount ); |
|
448 |
|
449 MPX_DEBUG2("CMPXCollectionOpenUtility::DoHandleCountL error %i <---", aError); |
|
450 TBool done(EFalse); |
|
451 if( aError == KErrNone ) |
|
452 { |
|
453 // Do we support incremental for this OpenL()? |
|
454 // |
|
455 TBool supportIncremental(EFalse); |
|
456 if( aEntries.IsSupported( KMPXCollectionOpenLSupportsIncremental ) ) |
|
457 { |
|
458 supportIncremental = aEntries.ValueTObjectL<TBool>( |
|
459 KMPXCollectionOpenLSupportsIncremental ); |
|
460 } |
|
461 |
|
462 if( supportIncremental ) |
|
463 { |
|
464 TInt count(0); |
|
465 if( aEntries.IsSupported(KMPXMediaArrayCount) ) |
|
466 { |
|
467 count = aEntries.ValueTObjectL<TInt>(KMPXMediaArrayCount); |
|
468 } |
|
469 |
|
470 if( iFetchInfo.iOffset == KErrNotFound ) |
|
471 { |
|
472 // If the client did not specify an offset |
|
473 // we use the index the collection is pointing to |
|
474 // as the starting offset |
|
475 // |
|
476 iFetchInfo.iOffset = aIndex; |
|
477 } |
|
478 if( count > 0 ) |
|
479 { |
|
480 // Perform the chunking here |
|
481 DoSetupChunksL( count ); |
|
482 DoCompactTaskListL( aEntries ); |
|
483 |
|
484 MPX_DEBUG2("CMPXCollectionOpenUtility::DoHandleCountL count %i", iIncrementalChunks.Count() ); |
|
485 if( iIncrementalChunks.Count() ) |
|
486 { |
|
487 // Start running the fetching algorithm |
|
488 iFetchStep = EFetchItems; |
|
489 iFirstOpen = ETrue; |
|
490 |
|
491 // Sync up the path, as there could have been items deleted |
|
492 delete iPath; |
|
493 iPath = NULL; |
|
494 iPath = iCollection->Collection().PathL(); |
|
495 |
|
496 if( iObs ) |
|
497 { |
|
498 iObs->HandleOpenL( aEntries, aIndex, EFalse, aError ); |
|
499 } |
|
500 RunNext(); |
|
501 } |
|
502 else |
|
503 { |
|
504 // Update index before returning |
|
505 DoSelectIndexL(); |
|
506 iFetchStep = EFetchNone; |
|
507 iCollection->Collection().OpenL(); |
|
508 done = EFalse; |
|
509 } |
|
510 } |
|
511 else |
|
512 { |
|
513 done = ETrue; |
|
514 } |
|
515 } |
|
516 else // !supportIncremental |
|
517 { |
|
518 // Just return the results |
|
519 // |
|
520 MPX_DEBUG1("CMPXCollectionOpenUtility::DoHandleCountL incremental not supported"); |
|
521 done = ETrue; |
|
522 } |
|
523 |
|
524 } |
|
525 if( (aError != KErrNone) || done ) |
|
526 { |
|
527 // Stop the OpenL() operation |
|
528 iFetchStep = EFetchNone; |
|
529 if( iObs ) |
|
530 { |
|
531 iObs->HandleOpenL( aEntries, aIndex, ETrue, aError ); |
|
532 } |
|
533 } |
|
534 } |
|
535 |
|
536 // --------------------------------------------------------------------------- |
|
537 // Fetch items step |
|
538 // --------------------------------------------------------------------------- |
|
539 // |
|
540 void CMPXCollectionOpenUtility::DoFetchItemsL() |
|
541 { |
|
542 // Construct a command to fetch the next chunk |
|
543 // |
|
544 MPX_DEBUG1("CMPXCollectionOpenUtility::DoFetchItemsL <---" ); |
|
545 if( iIncrementalChunks.Count() > 0 ) |
|
546 { |
|
547 CMPXCommand* command = CMPXCommand::NewL(); |
|
548 CleanupStack::PushL( command ); |
|
549 |
|
550 // Construct the command |
|
551 // |
|
552 TInt colId( iPath->Id(0) ); |
|
553 TInt offset( iIncrementalChunks[0].iOffset ); |
|
554 command->SetTObjectValueL( KMPXCommandGeneralId, |
|
555 KMPXCommandIdIncrementalOpenL ); |
|
556 command->SetTObjectValueL( KMPXCommandGeneralCollectionId, |
|
557 colId ); |
|
558 command->SetCObjectValueL(KMPXCollectionCommandIdIncOpenLPath,iPath ); |
|
559 command->SetTObjectValueL(KMPXCollectionCommandIdIncOpenLOffset, |
|
560 offset ); |
|
561 command->SetTObjectValueL(KMPXCollectionCommandIdIncOpenLNumItems, iFetchInfo.iSize); |
|
562 |
|
563 // If some partial data is available |
|
564 // try to optimize this by using the ascending or decending keys |
|
565 // |
|
566 if( iData ) |
|
567 { |
|
568 if( offset-1 > 0 && offset-1 < iData->Count() && |
|
569 iData->AtL(offset-1)->IsSupported(iKeyAttribute) ) |
|
570 { |
|
571 command->SetTObjectValueL(KMPXCollectionCommandIdIncOpenLAscDsc, EReadAscending); |
|
572 const TDesC& key = iData->AtL(offset-1)->ValueText(iKeyAttribute); |
|
573 command->SetTextValueL(KMPXCollectionCommandIdIncOpenLKeyItem,key); |
|
574 } |
|
575 else if( offset+iFetchInfo.iSize < iData->Count() && |
|
576 iData->AtL(offset+iFetchInfo.iSize)->IsSupported(iKeyAttribute) ) |
|
577 { |
|
578 command->SetTObjectValueL(KMPXCollectionCommandIdIncOpenLAscDsc, EReadDescending); |
|
579 const TDesC& key = iData->AtL(offset+iFetchInfo.iSize)->ValueText(iKeyAttribute); |
|
580 command->SetTextValueL(KMPXCollectionCommandIdIncOpenLKeyItem,key); |
|
581 } |
|
582 } |
|
583 |
|
584 // Command sent to the collection, callback HandleCommandComplete() |
|
585 // |
|
586 MPX_DEBUG2("CMPXCollectionOpenUtility::DoFetchItemsL offset %i <---", offset ); |
|
587 iFetchStep = EFetchCommand; |
|
588 iCollection->Collection().CommandL( *command ); |
|
589 CleanupStack::PopAndDestroy( command ); |
|
590 } |
|
591 MPX_DEBUG1("CMPXCollectionOpenUtility::DoFetchItemsL --->" ); |
|
592 } |
|
593 |
|
594 // --------------------------------------------------------------------------- |
|
595 // Handle Completion of fetch items step |
|
596 // --------------------------------------------------------------------------- |
|
597 // |
|
598 void CMPXCollectionOpenUtility::DoHandleFetchItemsL( const CMPXMedia& aEntries, |
|
599 TInt aIndex, |
|
600 TInt aError ) |
|
601 { |
|
602 MPX_DEBUG1("CMPXCollectionOpenUtility::DoHandleFetchItemsL <---" ); |
|
603 // Task is done, and compact the list |
|
604 // |
|
605 TInt curOffset(0); |
|
606 if( iIncrementalChunks.Count() ) |
|
607 { |
|
608 curOffset = iIncrementalChunks[0].iOffset; |
|
609 iIncrementalChunks.Remove(0); |
|
610 DoCompactTaskListL( aEntries ); |
|
611 } |
|
612 else |
|
613 { |
|
614 MPX_DEBUG1("CMPXCollectionOpenUtility::DoHandleFetchItemsL No more chunks" ); |
|
615 } |
|
616 |
|
617 TBool complete = iIncrementalChunks.Count() == 0 ? ETrue : EFalse; |
|
618 |
|
619 // Keep a reference here |
|
620 // |
|
621 delete iMedia; |
|
622 iMedia = NULL; |
|
623 iMedia = CMPXMedia::NewL( aEntries ); |
|
624 iData = NULL; |
|
625 if( aEntries.IsSupported( KMPXMediaArrayContents ) ) |
|
626 { |
|
627 iData = aEntries.Value<CMPXMediaArray>( KMPXMediaArrayContents ); |
|
628 User::LeaveIfNull(iData); |
|
629 } |
|
630 |
|
631 // Run the next step of the fetching algorithm |
|
632 // Do not run if stopped |
|
633 // |
|
634 TInt count(iIncrementalChunks.Count()); |
|
635 if( count != 0 && iFetchStep != EFetchNone ) |
|
636 { |
|
637 // Update the path, as the item IDs will be filled |
|
638 // |
|
639 MPX_DEBUG2("CMPXCollectionOpenUtility::DoHandleFetchItemsL run next %i", count ); |
|
640 delete iPath; |
|
641 iPath = NULL; |
|
642 iPath = iCollection->Collection().PathL(); |
|
643 |
|
644 // Command to fetch next chunk |
|
645 // |
|
646 RunNext(); |
|
647 } |
|
648 else |
|
649 { |
|
650 // All done |
|
651 iFetchStep = EFetchNone; |
|
652 } |
|
653 |
|
654 // Callback to observer with some treshold to avoid over redrawing |
|
655 // Playlists need every handle open to update the path |
|
656 // |
|
657 if( iObs && |
|
658 (Abs<TInt>(aIndex-curOffset) < iFetchInfo.iSize || |
|
659 iFirstOpen || iMode == KMcModePlaylist || complete ) ) |
|
660 { |
|
661 iFirstOpen = EFalse; |
|
662 MPX_DEBUG1("CMPXCollectionOpenUtility::DoHandleFetchItemsL callback" ); |
|
663 iObs->HandleOpenL( aEntries, aIndex, complete, aError ); |
|
664 } |
|
665 |
|
666 MPX_DEBUG1("CMPXCollectionOpenUtility::DoHandleFetchItemsL -->" ); |
|
667 } |
|
668 |
|
669 // --------------------------------------------------------------------------- |
|
670 // Run the next step |
|
671 // --------------------------------------------------------------------------- |
|
672 // |
|
673 void CMPXCollectionOpenUtility::RunNext() |
|
674 { |
|
675 TCallBack cb( Callback,this ); |
|
676 iTimer->Cancel(); |
|
677 iTimer->Start( TTimeIntervalMicroSeconds32( iFetchDelay ), |
|
678 TTimeIntervalMicroSeconds32( iFetchDelay ), |
|
679 cb); |
|
680 } |
|
681 |
|
682 // --------------------------------------------------------------------------- |
|
683 // Set some callback |
|
684 // --------------------------------------------------------------------------- |
|
685 // |
|
686 TInt CMPXCollectionOpenUtility::Callback( TAny* aAny ) |
|
687 { |
|
688 TRAP_IGNORE( ((CMPXCollectionOpenUtility*)aAny)->HandleCallbackL() ); |
|
689 return ETrue; |
|
690 } |
|
691 |
|
692 // --------------------------------------------------------------------------- |
|
693 // HandleCallback from iTimer |
|
694 // --------------------------------------------------------------------------- |
|
695 // |
|
696 void CMPXCollectionOpenUtility::HandleCallbackL() |
|
697 { |
|
698 switch( iFetchStep ) |
|
699 { |
|
700 case EFetchPath: |
|
701 { |
|
702 iCollection->Collection().OpenL( *iPath ); |
|
703 break; |
|
704 } |
|
705 case EFetchCount: |
|
706 { |
|
707 DoFetchCountL(); |
|
708 break; |
|
709 } |
|
710 case EFetchItems: |
|
711 { |
|
712 DoFetchItemsL(); |
|
713 break; |
|
714 } |
|
715 case EFetchNone: |
|
716 { |
|
717 break; // do nothing |
|
718 } |
|
719 default: |
|
720 { |
|
721 MPX_ASSERT(0); |
|
722 break; |
|
723 } |
|
724 } |
|
725 // Run once only |
|
726 iTimer->Cancel(); |
|
727 } |
|
728 |
|
729 // --------------------------------------------------------------------------- |
|
730 // Setup the chunks |
|
731 // --------------------------------------------------------------------------- |
|
732 // |
|
733 void CMPXCollectionOpenUtility::DoSetupChunksL( TInt aCount ) |
|
734 { |
|
735 // Number of chunks we are going to have |
|
736 // And the chunk the offset is going to be at |
|
737 // |
|
738 iIncrementalChunks.Reset(); |
|
739 |
|
740 TInt numChunks(0); |
|
741 if( aCount > 0 ) |
|
742 { |
|
743 // Truncate and add 1 if any modulus, no Ceil() function |
|
744 numChunks = (TInt)aCount/iFetchInfo.iSize; |
|
745 if( aCount % iFetchInfo.iSize ) |
|
746 { |
|
747 numChunks++; |
|
748 } |
|
749 } |
|
750 TInt offSetChunk = (TInt) iFetchInfo.iOffset / iFetchInfo.iSize ; |
|
751 |
|
752 // First chunk |
|
753 TMPXOpenDataBlock chunk; |
|
754 chunk.iOffset = offSetChunk*iFetchInfo.iSize; |
|
755 chunk.iSize = iFetchInfo.iSize; |
|
756 iIncrementalChunks.AppendL( chunk ); |
|
757 |
|
758 // Left and right of the first chunk |
|
759 TInt left = offSetChunk-1; |
|
760 TInt right = offSetChunk+1; |
|
761 TInt count(numChunks-1); |
|
762 while( count > 0 ) |
|
763 { |
|
764 // Append Left Chunk |
|
765 // |
|
766 TInt temp(left); |
|
767 if( left < 0 ) |
|
768 { |
|
769 // Wrap around to end of the list |
|
770 temp = numChunks + left; |
|
771 } |
|
772 chunk.iOffset = temp*iFetchInfo.iSize; |
|
773 iIncrementalChunks.AppendL( chunk ); |
|
774 MPX_DEBUG2("Adding Chunk %i", temp); |
|
775 |
|
776 count--; |
|
777 left--; |
|
778 |
|
779 // Append Right Chunk |
|
780 if( temp != right%numChunks ) |
|
781 { |
|
782 chunk.iOffset = (right%numChunks)*iFetchInfo.iSize; |
|
783 iIncrementalChunks.AppendL( chunk ); |
|
784 MPX_DEBUG2("Adding Chunk %i", right%numChunks); |
|
785 |
|
786 count--; |
|
787 right++; |
|
788 } |
|
789 } |
|
790 |
|
791 // Set the direction and re-order as necessary |
|
792 SetDirection( iFetchDirection ); |
|
793 } |
|
794 |
|
795 // --------------------------------------------------------------------------- |
|
796 // Sort the internal array ascending |
|
797 // --------------------------------------------------------------------------- |
|
798 // |
|
799 void CMPXCollectionOpenUtility::DoSortAscend( TBool aSkipFirst ) |
|
800 { |
|
801 if( iIncrementalChunks.Count() > 0 ) |
|
802 { |
|
803 TMPXOpenDataBlock tmp; |
|
804 if( aSkipFirst ) |
|
805 { |
|
806 tmp = iIncrementalChunks[0]; |
|
807 iIncrementalChunks.Remove(0); |
|
808 } |
|
809 iIncrementalChunks.Sort( CompareAsc ); |
|
810 |
|
811 if( aSkipFirst ) |
|
812 { |
|
813 iIncrementalChunks.Insert( tmp, 0 ); |
|
814 } |
|
815 } |
|
816 |
|
817 #ifdef _DEBUG |
|
818 TInt c=iIncrementalChunks.Count(); |
|
819 for( TInt i=0; i<c; ++i ) |
|
820 { |
|
821 MPX_DEBUG2("Order %i", iIncrementalChunks[i].iOffset); |
|
822 } |
|
823 #endif // _DEBUG |
|
824 } |
|
825 |
|
826 // --------------------------------------------------------------------------- |
|
827 // Sort the internal array decending |
|
828 // --------------------------------------------------------------------------- |
|
829 // |
|
830 void CMPXCollectionOpenUtility::DoSortDescend( TBool aSkipFirst ) |
|
831 { |
|
832 if( iIncrementalChunks.Count() > 0 ) |
|
833 { |
|
834 TMPXOpenDataBlock tmp; |
|
835 if( aSkipFirst ) |
|
836 { |
|
837 tmp = iIncrementalChunks[0]; |
|
838 iIncrementalChunks.Remove(0); |
|
839 } |
|
840 iIncrementalChunks.Sort( CompareDsc ); |
|
841 |
|
842 if( aSkipFirst ) |
|
843 { |
|
844 iIncrementalChunks.Insert( tmp, 0 ); |
|
845 } |
|
846 } |
|
847 |
|
848 #ifdef _DEBUG |
|
849 TInt c=iIncrementalChunks.Count(); |
|
850 for( TInt i=0; i<c; ++i ) |
|
851 { |
|
852 MPX_DEBUG2("Order %i", iIncrementalChunks[i].iOffset); |
|
853 } |
|
854 #endif // _DEBUG |
|
855 } |
|
856 |
|
857 // --------------------------------------------------------------------------- |
|
858 // Sort the internal array in normal form |
|
859 // --------------------------------------------------------------------------- |
|
860 // |
|
861 void CMPXCollectionOpenUtility::DoSortNormalL( TBool aSkipFirst ) |
|
862 { |
|
863 DoSortAscend( aSkipFirst ); |
|
864 |
|
865 RArray<TMPXOpenDataBlock> temp; |
|
866 CleanupClosePushL( temp ); |
|
867 |
|
868 TBool start = aSkipFirst ? 1:0; |
|
869 TInt count( iIncrementalChunks.Count() ); |
|
870 TInt c(count); |
|
871 if( aSkipFirst ) |
|
872 { |
|
873 temp.AppendL( iIncrementalChunks[0] ); |
|
874 count--; |
|
875 } |
|
876 |
|
877 TInt left(iIncrementalChunks.Count()/2); |
|
878 TInt right = left+1; |
|
879 while( count > 0) |
|
880 { |
|
881 if( left>=start ) |
|
882 { |
|
883 temp.AppendL( iIncrementalChunks[left] ); |
|
884 left--; |
|
885 count--; |
|
886 } |
|
887 if( right<c ) |
|
888 { |
|
889 temp.AppendL( iIncrementalChunks[right] ); |
|
890 right++; |
|
891 count--; |
|
892 } |
|
893 } |
|
894 |
|
895 // Copy the results |
|
896 iIncrementalChunks.Reset(); |
|
897 c= temp.Count(); |
|
898 for( TInt i=0; i<c; ++i ) |
|
899 { |
|
900 iIncrementalChunks.AppendL( temp[i] ); |
|
901 } |
|
902 CleanupStack::PopAndDestroy( &temp ); |
|
903 } |
|
904 |
|
905 // --------------------------------------------------------------------------- |
|
906 // Compact the internal task list |
|
907 // --------------------------------------------------------------------------- |
|
908 // |
|
909 void CMPXCollectionOpenUtility::DoCompactTaskListL( const CMPXMedia& aMedia ) |
|
910 { |
|
911 RArray<TMPXOpenDataBlock> datablocks; |
|
912 CleanupClosePushL( datablocks ); |
|
913 |
|
914 TInt c( iIncrementalChunks.Count() ); |
|
915 |
|
916 if( aMedia.IsSupported(KMPXCollectionOpenLAllResultRange) ) |
|
917 { |
|
918 // De-serialize from global data |
|
919 // |
|
920 const TDesC& buf = aMedia.ValueText(KMPXCollectionOpenLAllResultRange); |
|
921 CBufBase* buffer(NULL); |
|
922 MPXUser::CreateBufferL( buf, buffer ); |
|
923 CleanupStack::PushL( buffer ); |
|
924 ::CreateFromBufferL( *buffer, datablocks ); |
|
925 CleanupStack::PopAndDestroy( buffer ); |
|
926 |
|
927 // Remove un-necessary fetches |
|
928 TInt c2( datablocks.Count() ); |
|
929 for( TInt i=c-1; i>=0; --i ) |
|
930 { |
|
931 TMPXOpenDataBlock& chunk = iIncrementalChunks[i]; |
|
932 for( TInt j=0; j<c2; ++j ) |
|
933 { |
|
934 TMPXOpenDataBlock b = datablocks[j]; |
|
935 |
|
936 if( chunk.iOffset >= b.iOffset && |
|
937 chunk.iOffset+chunk.iSize <= b.iOffset+b.iSize ) |
|
938 { |
|
939 // Don't need to fetch what is already |
|
940 // available |
|
941 // |
|
942 iIncrementalChunks.Remove( i ); |
|
943 break; |
|
944 } |
|
945 } |
|
946 } |
|
947 } |
|
948 |
|
949 CleanupStack::PopAndDestroy( &datablocks ); |
|
950 } |
|
951 |
|
952 // --------------------------------------------------------------------------- |
|
953 // Update the selection index |
|
954 // --------------------------------------------------------------------------- |
|
955 // |
|
956 void CMPXCollectionOpenUtility::DoSelectIndexL() |
|
957 { |
|
958 CMPXCommand* command = CMPXCommand::NewL(); |
|
959 CleanupStack::PushL( command ); |
|
960 |
|
961 // Construct the command |
|
962 // |
|
963 command->SetTObjectValueL( KMPXCommandGeneralId, |
|
964 KMPXCommandIdCollectionSelect ); |
|
965 iCollection->Collection().CommandL( *command ); |
|
966 iSelecting = ETrue; |
|
967 CleanupStack::PopAndDestroy( command ); |
|
968 } |
|
969 // END OF FILE |