18 |
18 |
19 #include <mtp/mmtpdataproviderframework.h> |
19 #include <mtp/mmtpdataproviderframework.h> |
20 #include <mtp/mmtpobjectmgr.h> |
20 #include <mtp/mmtpobjectmgr.h> |
21 #include <mtp/mmtpstoragemgr.h> |
21 #include <mtp/mmtpstoragemgr.h> |
22 #include <mtp/cmtpobjectmetadata.h> |
22 #include <mtp/cmtpobjectmetadata.h> |
23 #include <hal.h> |
23 |
24 |
|
25 #include "mediamtpdataproviderconst.h" |
|
26 #include "cmediamtpdataproviderenumerator.h" |
24 #include "cmediamtpdataproviderenumerator.h" |
27 #include "cmediamtpdataprovider.h" |
25 #include "cmediamtpdataprovider.h" |
28 #include "mmmtpdplogger.h" |
26 #include "mmmtpdplogger.h" |
29 #include "mmmtpdputility.h" |
|
30 #include "cmmmtpdpaccesssingleton.h" |
|
31 #include "cmmmtpdpmetadataaccesswrapper.h" |
27 #include "cmmmtpdpmetadataaccesswrapper.h" |
32 |
|
33 |
|
34 #if defined(_DEBUG) || defined(MMMTPDP_PERFLOG) |
|
35 _LIT( KDirectoryScan, "DirectoryScan" ); |
|
36 _LIT( KFormatFilter, "FormatFilter" ); |
|
37 _LIT( KObjectManagerObjectUid, "ObjectManagerObjectUid" ); |
|
38 _LIT( KObjectManagerInsert, "ObjectManagerInsert" ); |
|
39 #endif |
|
40 |
|
41 // Unit: microsecond |
|
42 const TInt KThresholdOfEnumerationLoopDuration = 1000 * 1000; // microsecond |
|
43 |
28 |
44 const TInt KMTPDriveGranularity = 5; |
29 const TInt KMTPDriveGranularity = 5; |
45 const TInt KMediaDpArrayGranularity = 2; |
30 const TInt KMediaDpArrayGranularity = 2; |
46 |
31 |
47 // ----------------------------------------------------------------------------- |
32 // ----------------------------------------------------------------------------- |
175 // Cancel the enumeration process |
147 // Cancel the enumeration process |
176 // ----------------------------------------------------------------------------- |
148 // ----------------------------------------------------------------------------- |
177 // |
149 // |
178 void CMediaMtpDataProviderEnumerator::DoCancel() |
150 void CMediaMtpDataProviderEnumerator::DoCancel() |
179 { |
151 { |
180 iDir.Close(); |
152 } |
181 } |
153 |
182 |
154 // ----------------------------------------------------------------------------- |
183 // ----------------------------------------------------------------------------- |
155 // CMediaMtpDataProviderEnumerator::RunL |
184 // CMediaMtpDataProviderEnumerator::ScanStorageL |
156 // Update the mpx db flag for round trip |
185 // |
157 // ----------------------------------------------------------------------------- |
186 // ----------------------------------------------------------------------------- |
158 // |
187 // |
159 void CMediaMtpDataProviderEnumerator::RunL() |
188 void CMediaMtpDataProviderEnumerator::ScanStorageL( TUint32 aStorageId ) |
160 { |
189 { |
161 PRINT1( _L( "MM MTP => CMediaMtpDataProviderEnumerator::RunL iStorages.Count() = %d" ), iStorages.Count() ); |
190 const CMTPStorageMetaData& storage( iFramework.StorageMgr().StorageL( aStorageId ) ); |
162 |
191 |
163 if ( iStorages.Count() > 0 ) |
192 __ASSERT_DEBUG( ( storage.Uint( CMTPStorageMetaData::EStorageSystemType ) == CMTPStorageMetaData::ESystemTypeDefaultFileSystem ), |
164 { |
193 User::Invariant() ); |
|
194 |
|
195 TFileName root( storage.DesC( CMTPStorageMetaData::EStorageSuid ) ); |
|
196 PRINT2( _L("MM MTP <> CMediaMtpDataProviderEnumerator::ScanStorageL aStorageId = 0x%x, StorageSuid = %S"), aStorageId, &root ); |
|
197 |
|
198 iParentHandle = KMTPHandleNoParent; |
|
199 iPath.Set( root, NULL, NULL); |
|
200 iDir.Close(); |
|
201 User::LeaveIfError( iDir.Open( iFramework.Fs(), |
|
202 iPath.DriveAndPath(), |
|
203 KEntryAttNormal | KEntryAttDir ) ); |
|
204 ScanDirL(); |
|
205 } |
|
206 |
|
207 // ----------------------------------------------------------------------------- |
|
208 // CMediaMtpDataProviderEnumerator::ScanNextStorageL |
|
209 // |
|
210 // ----------------------------------------------------------------------------- |
|
211 // |
|
212 void CMediaMtpDataProviderEnumerator::ScanNextStorageL() |
|
213 { |
|
214 // If there are one or more unscanned storages left |
|
215 // (the currently scanned one is still on the list) |
|
216 if ( iStorages.Count() > 1 ) |
|
217 { |
|
218 // Round trip suppport |
|
219 const CMTPStorageMetaData& storage( iFramework.StorageMgr().StorageL( iStorages[0] ) ); |
165 const CMTPStorageMetaData& storage( iFramework.StorageMgr().StorageL( iStorages[0] ) ); |
220 TFileName root( storage.DesC( CMTPStorageMetaData::EStorageSuid ) ); |
166 const TDesC& root( storage.DesC( CMTPStorageMetaData::EStorageSuid ) ); |
221 GetModifiedContentL( root ); |
167 GetModifiedContentL( root ); |
222 TRAPD( err, iDataProvider.GetWrapperL().UpdateMusicCollectionL() ); |
168 TRAPD( err, iDataProvider.GetWrapperL().UpdateMusicCollectionL( root ) ); |
223 if ( err != KErrNone ) |
169 if ( err != KErrNone ) |
224 { |
170 { |
225 PRINT1( _L("MM MTP <> ScanNextStorageL, UpdateMusicCollectionL err =%d "), err ); |
171 PRINT1( _L("MM MTP <> CMediaMtpDataProviderEnumerator::RunL, UpdateMusicCollectionL err =%d "), err ); |
226 } |
172 } |
227 |
|
228 iStorages.Remove( 0 ); |
173 iStorages.Remove( 0 ); |
229 ScanStorageL( iStorages[0] ); |
|
230 } |
|
231 else |
|
232 { |
|
233 // Round trip suppport |
|
234 const CMTPStorageMetaData& storage( iFramework.StorageMgr().StorageL( iStorages[0] ) ); |
|
235 TFileName root( storage.DesC( CMTPStorageMetaData::EStorageSuid ) ); |
|
236 GetModifiedContentL( root ); |
|
237 |
|
238 // We are done |
|
239 iStorages.Reset(); |
|
240 |
|
241 SignalCompleteL( iDataProvider ); |
|
242 } |
|
243 } |
|
244 |
|
245 // ----------------------------------------------------------------------------- |
|
246 // CMediaMtpDataProviderEnumerator::ScanDirL |
|
247 // |
|
248 // ----------------------------------------------------------------------------- |
|
249 // |
|
250 void CMediaMtpDataProviderEnumerator::ScanDirL() |
|
251 { |
|
252 PRINT( _L( "MM MTP => CMediaMtpDataProviderEnumerator::ScanDirL" ) ); |
|
253 |
|
254 StartEnumerationCount(); |
|
255 |
|
256 iFirstUnprocessed = 0; |
|
257 |
|
258 iScanningDir = ETrue; |
|
259 PERFLOGSTART( KDirectoryScan ); |
|
260 iDir.Read( iEntries, iStatus ); |
|
261 SetActive(); |
|
262 |
|
263 PRINT( _L( "MM MTP <= CMediaMtpDataProviderEnumerator::ScanDirL" ) ); |
|
264 } |
|
265 |
|
266 // ----------------------------------------------------------------------------- |
|
267 // CMediaMtpDataProviderEnumerator::ScanNextDirL |
|
268 // Recurse into the next directory on the stack |
|
269 // and scan it for entries. |
|
270 // ----------------------------------------------------------------------------- |
|
271 // |
|
272 void CMediaMtpDataProviderEnumerator::ScanNextDirL() |
|
273 { |
|
274 TInt count = iDirStack.Count(); |
|
275 |
|
276 if ( count == 0 ) |
|
277 { |
|
278 // No more directories on the stack, try the next storage |
|
279 ScanNextStorageL(); |
|
280 } |
|
281 else |
|
282 { |
|
283 TEntry* entry = iDirStack[count - 1]; |
|
284 if ( entry != NULL ) |
|
285 { |
|
286 |
|
287 // Empty TEntry, no more subdirectories in |
|
288 // the current path |
|
289 if ( entry->iName == KNullDesC ) |
|
290 { |
|
291 // Remove current dir from path |
|
292 iPath.PopDir(); |
|
293 iDirStack.Remove( count - 1 ); |
|
294 delete entry; |
|
295 entry = NULL; |
|
296 iDir.Close(); |
|
297 |
|
298 // Scan the next directory of the parent |
|
299 ScanNextDirL(); |
|
300 } |
|
301 // Going into a subdirectory of current |
|
302 else |
|
303 { |
|
304 // Add directory to path |
|
305 iPath.AddDir( entry->iName ); |
|
306 // Remove directory so we don't think it's a subdirectory |
|
307 iDirStack.Remove( count - 1 ); |
|
308 delete entry; |
|
309 entry = NULL; |
|
310 ScanNextSubdirL(); |
|
311 } |
|
312 } |
|
313 } |
|
314 } |
|
315 |
|
316 // ----------------------------------------------------------------------------- |
|
317 // CMediaMtpDataProviderEnumerator::ScanNextSubdirL |
|
318 // Scan next sub dir |
|
319 // ----------------------------------------------------------------------------- |
|
320 // |
|
321 void CMediaMtpDataProviderEnumerator::ScanNextSubdirL() |
|
322 { |
|
323 PRINT( _L( "MM MTP => CMediaMtpDataProviderEnumerator::ScanNextSubdirL" ) ); |
|
324 |
|
325 // A empty (non-constructed) TEntry is our marker telling us to pop a directory |
|
326 // from iPath when we see this |
|
327 TEntry* entry = new TEntry( TEntry() ); |
|
328 |
|
329 User::LeaveIfNull( entry ); |
|
330 |
|
331 iDirStack.AppendL( entry ); |
|
332 |
|
333 // Leave with KErrNotFound if we don't find the object handle since it shouldn't be on the |
|
334 // dirstack if the entry wasn't added |
|
335 TPtrC suid = iPath.DriveAndPath().Left( iPath.DriveAndPath().Length() ); |
|
336 // Update the current parenthandle with object of the directory |
|
337 PERFLOGSTART( KObjectManagerObjectUid ); |
|
338 iParentHandle = iFramework.ObjectMgr().HandleL( suid ); |
|
339 PERFLOGSTOP( KObjectManagerObjectUid ); |
|
340 PRINT1( _L( "MM MTP <> iParentHandle = 0x%x" ), iParentHandle ); |
|
341 |
|
342 // Kick-off a scan of the next directory |
|
343 iDir.Close(); |
|
344 |
|
345 TInt err = iDir.Open( iFramework.Fs(), |
|
346 iPath.DriveAndPath(), |
|
347 KEntryAttNormal | KEntryAttDir ); |
|
348 |
|
349 PRINT1( _L( "MM MTP <> CMediaMtpDataProviderEnumerator::ScanNextSubdirL, RDir::Open err = %d" ), err ); |
|
350 |
|
351 if ( err == KErrNone ) |
|
352 ScanDirL(); |
|
353 else |
|
354 { |
|
355 iEntries = TEntryArray(); |
|
356 |
|
357 TRequestStatus* status = &iStatus; |
174 TRequestStatus* status = &iStatus; |
358 User::RequestComplete( status, iStatus.Int() ); |
175 User::RequestComplete( status, iStatus.Int() ); |
359 SetActive(); |
176 SetActive(); |
360 } |
177 } |
361 |
|
362 |
|
363 PRINT( _L( "MM MTP <= CMediaMtpDataProviderEnumerator::ScanNextSubdirL" ) ); |
|
364 } |
|
365 |
|
366 // ----------------------------------------------------------------------------- |
|
367 // CMediaMtpDataProviderEnumerator::RunL |
|
368 // |
|
369 // ----------------------------------------------------------------------------- |
|
370 // |
|
371 void CMediaMtpDataProviderEnumerator::RunL() |
|
372 { |
|
373 if ( iScanningDir ) |
|
374 { |
|
375 PERFLOGSTOP( KDirectoryScan ); |
|
376 } |
|
377 |
|
378 iScanningDir = EFalse; |
|
379 if ( iEntries.Count() == 0 ) |
|
380 { |
|
381 // No entries to process, scan next dir or storage |
|
382 ScanNextDirL(); |
|
383 } |
|
384 else if ( iFirstUnprocessed < iEntries.Count() ) |
|
385 { |
|
386 PRINT1( _L( "MM MTP <> CMediaMtpDataProviderEnumerator::RunL iFirstUnprocessed = %d" ), iFirstUnprocessed); |
|
387 TRAPD( err, ProcessEntriesL();); |
|
388 if ( err != KErrNone ) |
|
389 { |
|
390 iFirstUnprocessed++; |
|
391 } |
|
392 |
|
393 // Complete ourselves with current TRequestStatus |
|
394 // since we need to run again to either scan a new dir or drive |
|
395 // or process more entries |
|
396 TRequestStatus* status = &iStatus; |
|
397 User::RequestComplete( status, iStatus.Int() ); |
|
398 SetActive(); |
|
399 } |
|
400 else |
178 else |
401 { |
179 { |
402 switch ( iStatus.Int() ) |
180 iStorages.Reset(); |
403 { |
181 SignalCompleteL( iDataProvider ); |
404 case KErrNone: |
182 } |
405 // There are still entries left to be read |
183 PRINT( _L( "MM MTP <= CMediaMtpDataProviderEnumerator::RunL" ) ); |
406 ScanDirL(); |
|
407 break; |
|
408 |
|
409 case KErrEof: |
|
410 // There are no more entries |
|
411 default: |
|
412 // Error, ignore and continue with next dir |
|
413 ScanNextDirL(); |
|
414 break; |
|
415 } |
|
416 } |
|
417 } |
184 } |
418 |
185 |
419 // ----------------------------------------------------------------------------- |
186 // ----------------------------------------------------------------------------- |
420 // CMediaMtpDataProviderEnumerator::RunError |
187 // CMediaMtpDataProviderEnumerator::RunError |
421 // |
188 // |
460 void CMediaMtpDataProviderEnumerator::SignalCompleteL( MMTPEnumerationCallback& aCallback, |
220 void CMediaMtpDataProviderEnumerator::SignalCompleteL( MMTPEnumerationCallback& aCallback, |
461 TInt aError/* = KErrNone*/) |
221 TInt aError/* = KErrNone*/) |
462 { |
222 { |
463 // Enumeration completed on this drive |
223 // Enumeration completed on this drive |
464 aCallback.NotifyEnumerationCompleteL( iStorageId, aError ); |
224 aCallback.NotifyEnumerationCompleteL( iStorageId, aError ); |
465 } |
|
466 |
|
467 // ----------------------------------------------------------------------------- |
|
468 // CMediaMtpDataProviderEnumerator::ProcessEntriesL |
|
469 // Iterates iEntries adding entries as needed to object manager and iDirStack. |
|
470 // ----------------------------------------------------------------------------- |
|
471 // |
|
472 void CMediaMtpDataProviderEnumerator::ProcessEntriesL() |
|
473 { |
|
474 PRINT( _L( "MM MTP => CMediaMtpDataProviderEnumerator::ProcessEntriesL" ) ); |
|
475 |
|
476 TFileName path = iPath.DriveAndPath(); |
|
477 |
|
478 while ( !IsOverThreshold() && iFirstUnprocessed < iEntries.Count() ) |
|
479 { |
|
480 const TEntry& entry = iEntries[iFirstUnprocessed]; |
|
481 |
|
482 TInt len = entry.iName.Length(); |
|
483 |
|
484 // Skip object with too long name |
|
485 if ( KMaxFileName >= path.Length() + len ) |
|
486 { |
|
487 path.Append( entry.iName ); |
|
488 PRINT1( _L( "MM MTP <> path = %S" ), &path ); |
|
489 |
|
490 if ( entry.IsDir() ) |
|
491 { |
|
492 path.Append( '\\' ); |
|
493 ++len; |
|
494 |
|
495 // we don't need to process folder, just remember |
|
496 // the folder |
|
497 TEntry* dirEntry = new TEntry( entry ); |
|
498 User::LeaveIfNull( dirEntry ); |
|
499 iDirStack.AppendL( dirEntry ); |
|
500 } |
|
501 else if ( IsFileAccepted( path ) ) |
|
502 { |
|
503 AddEntryL( path ); |
|
504 } |
|
505 |
|
506 // Remove filename part |
|
507 path.SetLength( path.Length() - len ); |
|
508 } |
|
509 |
|
510 iFirstUnprocessed++; |
|
511 } |
|
512 |
|
513 StartEnumerationCount(); |
|
514 PRINT( _L( "MM MTP <= CMediaMtpDataProviderEnumerator::ProcessEntriesL" ) ); |
|
515 } |
|
516 |
|
517 // ----------------------------------------------------------------------------- |
|
518 // CMediaMtpDataProviderEnumerator::AddEntryL |
|
519 // Add a file entry to the object store |
|
520 // ----------------------------------------------------------------------------- |
|
521 // |
|
522 void CMediaMtpDataProviderEnumerator::AddEntryL( const TDesC& aFullFileName ) |
|
523 { |
|
524 PRINT1( _L( "MM MTP => CMediaDataProviderEnumerator::AddEntryL aFullFileName = %S" ), &aFullFileName ); |
|
525 |
|
526 CMTPObjectMetaData* object( CMTPObjectMetaData::NewLC( iDataProviderId, |
|
527 iFormatCode, |
|
528 iStorages[0], |
|
529 aFullFileName ) ); // + object |
|
530 |
|
531 object->SetUint( CMTPObjectMetaData::EParentHandle, iParentHandle ); |
|
532 |
|
533 if ( ( iFormatCode == EMTPFormatCodeMP4Container ) |
|
534 || ( iFormatCode == EMTPFormatCode3GPContainer ) |
|
535 || ( iFormatCode == EMTPFormatCodeASF ) ) |
|
536 { |
|
537 TMmMtpSubFormatCode subFormatCode; |
|
538 |
|
539 // Note: Delay the file parsing until external enumeration phase to avoid time-out |
|
540 subFormatCode = EMTPSubFormatCodeUnknown; |
|
541 |
|
542 object->SetUint( CMTPObjectMetaData::EFormatSubCode, (TUint)subFormatCode ); |
|
543 } |
|
544 |
|
545 PERFLOGSTART( KObjectManagerInsert ); |
|
546 iObjectMgr.InsertObjectL( *object ); |
|
547 PERFLOGSTOP( KObjectManagerInsert ); |
|
548 |
|
549 CleanupStack::PopAndDestroy( object ); // - object |
|
550 |
|
551 PRINT1( _L( "MM MTP <= CMediaMtpDataProviderEnumerator::AddEntryL, entry inserted, iFormatCode = 0x%x" ), iFormatCode); |
|
552 } |
|
553 |
|
554 // ----------------------------------------------------------------------------- |
|
555 // CMediaMtpDataProviderEnumerator::GetObjectFormatCode |
|
556 // Returns a TMTPFormatCode for the requested object |
|
557 // ----------------------------------------------------------------------------- |
|
558 // |
|
559 TMTPFormatCode CMediaMtpDataProviderEnumerator::GetObjectFormatCode( const TDesC& aFullFileName ) |
|
560 { |
|
561 PRINT1( _L("MM MTP <> CMediaMtpDataProviderEnumerator::GetObjectFormatCodeL aFullFileName = %S"), &aFullFileName ); |
|
562 TMTPFormatCode formatCode = MmMtpDpUtility::FormatFromFilename( aFullFileName ); |
|
563 return formatCode; |
|
564 } |
|
565 |
|
566 // ----------------------------------------------------------------------------- |
|
567 // CMediaMtpDataProviderEnumerator::IsFileAccepted |
|
568 // Is the file format is supported by this Dp |
|
569 // ----------------------------------------------------------------------------- |
|
570 // |
|
571 TBool CMediaMtpDataProviderEnumerator::IsFileAccepted( const TDesC& aFullFileName ) |
|
572 { |
|
573 PERFLOGSTART( KFormatFilter ); |
|
574 iFormatCode = GetObjectFormatCode( aFullFileName ); |
|
575 PRINT1( _L( "MM MTP <> CMediaMtpDataProviderEnumerator::IsFileAcceptedL formatCode = 0x%x" ), iFormatCode ); |
|
576 TBool accepted = EFalse; |
|
577 TInt count = sizeof( KMediaMtpDataProviderSupportedFormats ) / sizeof( TUint16 ); |
|
578 for ( TInt i = 0; i < count; i++ ) |
|
579 { |
|
580 if ( iFormatCode == KMediaMtpDataProviderSupportedFormats[i] ) |
|
581 { |
|
582 accepted = ETrue; |
|
583 break; |
|
584 } |
|
585 } |
|
586 |
|
587 PERFLOGSTOP( KFormatFilter ); |
|
588 return accepted; |
|
589 } |
|
590 |
|
591 // ----------------------------------------------------------------------------- |
|
592 // CMediaDpMtpEnumerator::StartEnumerationCount |
|
593 // start record system tick |
|
594 // ----------------------------------------------------------------------------- |
|
595 // |
|
596 void CMediaMtpDataProviderEnumerator::StartEnumerationCount() |
|
597 { |
|
598 iTickCountBegin = User::TickCount(); |
|
599 } |
|
600 |
|
601 // ----------------------------------------------------------------------------- |
|
602 // CMediaDpMtpEnumerator::IsOverThreshold |
|
603 // Is system tick more than the predefined value? |
|
604 // ----------------------------------------------------------------------------- |
|
605 // |
|
606 TBool CMediaMtpDataProviderEnumerator::IsOverThreshold() |
|
607 { |
|
608 TUint tcNow = User::TickCount(); |
|
609 |
|
610 if ( ( tcNow - iTickCountBegin ) * iTickPeriod >= KThresholdOfEnumerationLoopDuration ) |
|
611 { |
|
612 return ETrue; |
|
613 } |
|
614 else |
|
615 { |
|
616 return EFalse; |
|
617 } |
|
618 } |
225 } |
619 |
226 |
620 // ----------------------------------------------------------------------------- |
227 // ----------------------------------------------------------------------------- |
621 // CMediaDpMtpEnumerator::GetModifiedContentL() |
228 // CMediaDpMtpEnumerator::GetModifiedContentL() |
622 // Get Modified Content and report to Framework |
229 // Get Modified Content and report to Framework |