camerauis/cameraapp/generic/src/camfolderutility.cpp
branchRCL_3
changeset 24 bac7acad7cb3
child 25 2c87b2808fd7
equal deleted inserted replaced
23:61bc0f252b2b 24:bac7acad7cb3
       
     1 /*
       
     2 * Copyright (c) 2007-2008 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:  
       
    15 *
       
    16 *  Copyright © 2007-2008 Nokia.  All rights reserved.
       
    17 *  This material, including documentation and any related computer
       
    18 *  programs, is protected by copyright controlled by Nokia.  All
       
    19 *  rights are reserved.  Copying, including reproducing, storing,
       
    20 *  adapting or translating, any or all of this material requires the
       
    21 *  prior written consent of Nokia.  This material also contains
       
    22 *  confidential information which may not be disclosed to others
       
    23 *  without the prior written consent of Nokia.
       
    24 
       
    25 *
       
    26 *
       
    27 */
       
    28 
       
    29 
       
    30 // ===========================================================================
       
    31 // Included headers
       
    32 
       
    33 
       
    34 #include <bldvariant.hrh> // for feature definitions
       
    35 
       
    36 #include <f32file.h>
       
    37 #include <centralrepository.h>
       
    38 #include <pathinfo.h>
       
    39 #include <StringLoader.h>
       
    40 
       
    41 #include <cameraapp.rsg>
       
    42 #include <vgacamsettings.rsg>
       
    43 
       
    44 #include "CamPanic.h"
       
    45 #include "CamUtility.h"       // PRINT macros
       
    46 #include "CameraappPrivateCRKeys.h"  
       
    47 #include "camfolderutility.h"
       
    48 
       
    49 
       
    50 // ===========================================================================
       
    51 // Local constants
       
    52 
       
    53 static const TInt KMultipleFolderNumberChars = 2;
       
    54 static const TInt KMaxMonthFolders           = 260;
       
    55 static const TInt KBase10                    = 10;
       
    56 static const TInt KCamMonthFolderNameLength = 8;
       
    57 
       
    58 
       
    59 _LIT( KCamMonthFolderFormat, "%F%Y%M" );  
       
    60 _LIT( KBackslash,            "\\"     );
       
    61 _LIT( KCharacterOffset,      "A"      );
       
    62 _LIT( KDigitOffset,          "0"      );
       
    63 _LIT( KMaxCharacter,         "Z"      );
       
    64 _LIT( KWildCardCharacter,    "?"      );
       
    65 
       
    66 
       
    67 
       
    68 // ===========================================================================
       
    69 // CCamFolderUtility implementation
       
    70 
       
    71 // ---------------------------------------------------------------------------
       
    72 // GetBasePathL
       
    73 // Generates the path where new images/videos are to be saved to.
       
    74 // ---------------------------------------------------------------------------
       
    75 //
       
    76 void
       
    77 CCamFolderUtility::GetBasePathL( TInt*                 aMonthCounters,
       
    78                                  TInt                  aStorage, // TCamMediaStorage
       
    79                                  TDes&                 aPath, 
       
    80                                  TCamCameraMode aCaptureMode, 
       
    81                                  TBool                 aCreateAll,
       
    82                                  TInt                  aRequiredFileCount,
       
    83                                  TTime                 aTime )
       
    84   {
       
    85   PRINT( _L("Camera => CCamFolderUtility::GetBasePathL"))
       
    86 
       
    87   TInt folderTypeIndex = 0;
       
    88   
       
    89     if ( ( aStorage == ECamMediaStoragePhone ) ) // Saving to phone memory
       
    90        { 
       
    91        // phone folders are in the odd indexes
       
    92        folderTypeIndex ++;
       
    93        PRINT( _L("Camera GetBasePathL saving to phone memory"))
       
    94        aPath.Copy( PathInfo::PhoneMemoryRootPath() );
       
    95        }
       
    96        // with multiple drives, mass storage is the default, like phone memory used to be.
       
    97     else if ( aStorage == ECamMediaStorageMassStorage ) // Saving to mass storage memory
       
    98        {
       
    99        PRINT( _L("Camera GetBasePathL saving to mass storage memory"))
       
   100        // Get the root path of the mass storage drive.
       
   101        TInt drive;
       
   102        TInt err = DriveInfo::GetDefaultDrive( DriveInfo::EDefaultMassStorage, drive );
       
   103        TFileName path;
       
   104        err = PathInfo::GetRootPath( path, drive );
       
   105        aPath.Copy(path);
       
   106        }
       
   107     else  // Saving to MMC
       
   108        {
       
   109        PRINT( _L("Camera GetBasePathL saving to memory card"))
       
   110        // Get the root path of the mmc.
       
   111        TInt drive;
       
   112        TInt err = DriveInfo::GetDefaultDrive( DriveInfo::EDefaultRemovableMassStorage, drive );
       
   113        TFileName path;
       
   114        err = PathInfo::GetRootPath( path, drive );
       
   115        aPath.Copy(path);
       
   116        }
       
   117 
       
   118      // Append the folder to the path
       
   119   if ( ECamControllerVideo == aCaptureMode )
       
   120       {
       
   121       aPath.Append( PathInfo::VideosPath() );
       
   122       // video folders are offset to ECamFolderTypeVideoMMC
       
   123       folderTypeIndex += ECamFolderTypeVideoMMC;
       
   124       }
       
   125   else 
       
   126       {
       
   127       aPath.Append( PathInfo::ImagesPath() );  
       
   128       }             
       
   129     // Copied from below
       
   130     TBuf<KMaxNameBaseLength> cameraFolder; // "Camera"
       
   131     StringLoader::Load( cameraFolder, R_CAM_CAMERA_SUBFOLDER );
       
   132     
       
   133     RFs rfs;
       
   134     User::LeaveIfError( rfs.Connect() );
       
   135     CleanupClosePushL( rfs );     
       
   136  
       
   137     TFileName fn( aPath );
       
   138     fn.Append( cameraFolder );
       
   139     TEntry entry;
       
   140     TInt err2 = rfs.Entry(fn, entry );
       
   141 
       
   142     if( KErrNone == err2 )
       
   143       {
       
   144        if (!entry.IsDir( ))
       
   145           {
       
   146            RBuf newName;
       
   147            CleanupClosePushL( newName);  
       
   148            newName.CreateL( fn.Length() + 4 );
       
   149            newName.Copy( fn );
       
   150            newName.Append(_L(".bak"));
       
   151            TInt error = rfs.Rename( fn, newName );
       
   152            if ( error != KErrNone )
       
   153                {
       
   154                 User::LeaveIfError( rfs.Delete( fn ) );
       
   155                }
       
   156            CleanupStack::PopAndDestroy( &newName );
       
   157           }
       
   158        }
       
   159   // Add a folder for the current month
       
   160   // Use the specified time to determine the year and month.
       
   161   // If this is 0 then use the current time.
       
   162   TTime now = aTime;
       
   163   if ( now.Int64() == TInt64( 0 ) )
       
   164       {
       
   165       now.HomeTime();
       
   166       }
       
   167   TBuf<KCamMonthFolderNameLength> monthFolder;
       
   168   now.FormatL( monthFolder, KCamMonthFolderFormat );
       
   169   // If the month folder name is different to the last used month folder name
       
   170   // this indicates that a new month has been started. All the counters will
       
   171   // need to be reinitialised
       
   172   
       
   173   // Get last used folder name
       
   174   TBuf<KCamMonthFolderNameLength> previousMonthFolder;
       
   175   CRepository* cr = CRepository::NewLC( KCRUidCameraappSettings );
       
   176   cr->Get( KCamCrLastUsedMonthFolder, previousMonthFolder );
       
   177   
       
   178   // Compare to current folder name, if different then reset all counters
       
   179   if ( monthFolder.Compare( previousMonthFolder) != 0 )
       
   180       {
       
   181       ResetCounters( aMonthCounters );
       
   182       // Write month folder name to shared data 
       
   183       cr->Set( KCamCrLastUsedMonthFolder, monthFolder );
       
   184       }  
       
   185   CleanupStack::PopAndDestroy( cr );    
       
   186 //  TBuf<KMaxNameBaseLength> cameraFolder;
       
   187 //  StringLoader::Load( cameraFolder, R_CAM_CAMERA_SUBFOLDER );
       
   188   aPath.Append( cameraFolder );   
       
   189   aPath.Append( KBackslash );          
       
   190   aPath.Append( monthFolder );  
       
   191   aPath.Append( KBackslash ); 
       
   192   
       
   193   // Keep track of the month folder (YYYYMM) name length
       
   194   // This may be returned e.g.if the month counter destination folder  (YYYYMMXX) is
       
   195   // not created
       
   196   TInt monthFolderLength = aPath.Length();
       
   197 
       
   198   // ensure the path exists
       
   199   TInt err = rfs.MkDirAll( aPath );
       
   200  
       
   201   // If the folder is newly created then set the counter to 0  
       
   202   if      ( KErrNone          == err ) aMonthCounters[folderTypeIndex] = 0;
       
   203   else if ( KErrAlreadyExists == err ) err = KErrNone;
       
   204   else                                 User::Leave( err );
       
   205 
       
   206           
       
   207   // If the month counter is uninitialised it needs to be set up
       
   208   if ( aMonthCounters[folderTypeIndex] < 0 )
       
   209       {
       
   210       User::LeaveIfError( InitialiseMonthCounter( aMonthCounters,
       
   211                                                   aPath,
       
   212                                                   monthFolder,
       
   213                                                   rfs,
       
   214                                                   folderTypeIndex ) );
       
   215       }
       
   216   aPath.Append( monthFolder ); 
       
   217   // Only ensure the folder exists (and has space) if the aCreateAll flag is set
       
   218   if ( aCreateAll )
       
   219       {
       
   220       PRINT( _L("Camera GetBasePathL creating month counter folder") )
       
   221       // This adds on the correct counter if completing without error
       
   222       User::LeaveIfError( CreateDestinationFolder( aMonthCounters,
       
   223                                                    aPath, 
       
   224                                                    rfs, 
       
   225                                                    folderTypeIndex, 
       
   226                                                    aRequiredFileCount ) );
       
   227       }
       
   228   else
       
   229       {
       
   230       TInt monthCounter = aMonthCounters[folderTypeIndex];
       
   231       aPath.Append( KCharacterOffset()[0] + monthCounter/KBase10 );
       
   232       aPath.Append( KDigitOffset()[0] + monthCounter%KBase10 );
       
   233       aPath.Append( KBackslash );
       
   234       // If the folder does not exist then remove the final folder name from the path
       
   235       //TEntry entry;
       
   236       
       
   237       if ( rfs.Entry( aPath, entry ) == KErrNotFound )
       
   238           {
       
   239           aPath.SetLength( monthFolderLength );
       
   240           }
       
   241       }        
       
   242   CleanupStack::PopAndDestroy( &rfs );
       
   243 
       
   244   PRINT( _L("Camera <= CCamAppController::GetBasePathL returning") )
       
   245   }
       
   246 
       
   247 
       
   248 // ---------------------------------------------------------------------------
       
   249 // ResetCounters
       
   250 // ---------------------------------------------------------------------------
       
   251 //
       
   252 void 
       
   253 CCamFolderUtility::ResetCounters( TInt* aMonthCounters,
       
   254                                   TInt  aFrom,
       
   255                                   TInt  aTo )
       
   256   {
       
   257   PRINT( _L("Camera => CCamFolderUtility::ResetCounters") )
       
   258     {
       
   259     for( TInt i = aFrom; i <= aTo; i++ )
       
   260       {
       
   261       aMonthCounters[i] = -1;
       
   262       }
       
   263     }
       
   264   }
       
   265 
       
   266 
       
   267 
       
   268 // ---------------------------------------------------------------------------
       
   269 // InitialiseMonthCounter
       
   270 // Sets the value of the folder counter for the current month/media store/mode
       
   271 // ---------------------------------------------------------------------------
       
   272 //  
       
   273 TInt 
       
   274 CCamFolderUtility::InitialiseMonthCounter( TInt*  aMonthCounters,
       
   275                                            TDes&  aPath,
       
   276                                            TDesC& aMonthFolder,
       
   277                                            RFs&   aFs,
       
   278                                            TInt   aFolderType )
       
   279   {
       
   280   PRINT( _L("Camera => CCamFolderUtility::InitialiseMonthCounter") )
       
   281 
       
   282   // start by initialising the appropriate folder counter to 0
       
   283   aMonthCounters[aFolderType] = 0; 
       
   284       
       
   285   TInt monthFolderLength = aPath.Length();
       
   286   // The month counter folder starts with the same characters as the parent month folder
       
   287   aPath.Append( aMonthFolder );  
       
   288   TInt charCount;
       
   289   // Add on '??' wildcard characters to get a list of all folders with this 
       
   290   // month's format
       
   291   for ( charCount = 0; charCount < KMultipleFolderNumberChars; charCount++ )
       
   292       {
       
   293       aPath.Append( KWildCardCharacter );
       
   294       }
       
   295   // Get a list of folders for this month, sorted in descending alphabetical order
       
   296   // the first entry should be the latest used folder
       
   297   CDir* dirList;
       
   298   TInt err = KErrNone;
       
   299   err =  aFs.GetDir( aPath,
       
   300                      KEntryAttMatchExclusive|KEntryAttDir,
       
   301                      ESortByName|EDescending,
       
   302                      dirList );
       
   303   // Prune back to the parent folder path                           
       
   304   aPath.SetLength( monthFolderLength );                           
       
   305   if ( err == KErrNone )                           
       
   306     {
       
   307     TInt monthFolderCount = dirList->Count();                
       
   308     TInt index = 0;
       
   309     TBool done = EFalse;
       
   310     // Look through the list of folders in the month for the highest numbered folder
       
   311     // with the format YYYYMMAX Where YYYY is the year MM is the month A is an alphabetical
       
   312     // character in the range a-z or A-Z and X is a digit 0-9
       
   313     while ( index < monthFolderCount && !done )
       
   314       {
       
   315       done = ETrue;
       
   316       // The list is sorted in descending order. Get the last 2 characters from
       
   317       // the first directory in the list these indicate the highest folder number
       
   318       TPtrC name = ( *dirList )[index].iName; 
       
   319       TInt nameLength = name.Length();
       
   320       // Check the first character is in the range a-z or A-Z
       
   321       TChar firstChar = name[nameLength - KMultipleFolderNumberChars];
       
   322       firstChar.UpperCase();
       
   323       // If the character is not in the range then disregard this folder
       
   324       if ( firstChar < KCharacterOffset()[0] ||
       
   325            firstChar > KMaxCharacter()[0] )
       
   326         {
       
   327         done = EFalse;
       
   328         }
       
   329       // Check the second character is in the range 0-9                
       
   330       TChar secondChar = name[nameLength - 1];
       
   331       TInt secondCharVal = secondChar.GetNumericValue();
       
   332       if ( secondCharVal < 0 ||
       
   333            secondCharVal > KBase10 - 1 )
       
   334         {
       
   335         done = EFalse;
       
   336         }   
       
   337       if ( done )                             
       
   338         {
       
   339         TUint folderNumber = firstChar;
       
   340         // 10's part of folder number is represented by characters A-Z
       
   341         // convert the character into a decimal value
       
   342         folderNumber -= KCharacterOffset()[0];
       
   343         folderNumber *= KBase10; 
       
   344         // Now add on the units
       
   345         folderNumber += secondCharVal;
       
   346         aMonthCounters[aFolderType] = folderNumber;
       
   347         }
       
   348       // TUint folderNumber = name[nameLength - 2];       
       
   349       index++;   
       
   350       } 
       
   351     }
       
   352   delete dirList;  
       
   353   dirList = NULL;     
       
   354 
       
   355   PRINT1( _L("Camera <= CCamAppController::InitialiseMonthCounter returning %d"), err)
       
   356   return err;      
       
   357   }
       
   358   
       
   359 // ---------------------------------------------------------------------------
       
   360 // CreateDestinationFolder
       
   361 // Creates the folder where new images/videos are to be saved to.
       
   362 // ---------------------------------------------------------------------------
       
   363 //
       
   364 TInt 
       
   365 CCamFolderUtility::CreateDestinationFolder( TInt* aMonthCounters,
       
   366                                             TDes& aPath,
       
   367                                             RFs&  aFs, 
       
   368                                             TInt  aFolderType,
       
   369                                             TInt  aRequiredFileCount )    
       
   370   {
       
   371   PRINT( _L("Camera => CCamFolderUtility::CreateDestinationFolder ") ) 
       
   372   __ASSERT_DEBUG( aFolderType < ECamFolderTypeLast, CamPanic( ECamPanicBadIndex ) );
       
   373 
       
   374   TInt folderCreated = EFalse;
       
   375   // This error value will only be retained if the counter is outside
       
   376   // the allowed range 
       
   377   TInt err = KErrArgument; 
       
   378   TInt monthCounter = aMonthCounters[aFolderType];
       
   379   while ( !folderCreated && monthCounter < KMaxMonthFolders )
       
   380     {
       
   381     aMonthCounters[aFolderType] = monthCounter;
       
   382     err = KErrNone;   
       
   383     // Add on the new counter
       
   384     aPath.Append( KCharacterOffset()[0] + monthCounter/KBase10 );
       
   385     aPath.Append( KDigitOffset()[0] + monthCounter%KBase10 );
       
   386     aPath.Append( KBackslash );
       
   387     err = aFs.MkDirAll( aPath );
       
   388     PRINT1( _L("Camera <> MkDirAll returned %d "), err ) 
       
   389     // If the folder already exists then check there is enough space for the required file count
       
   390     if ( err == KErrAlreadyExists )
       
   391       {
       
   392       PRINT( _L("Camera <> MkDirAll KErrALreadyExists ") ) 
       
   393       // if this is the final folder (Z9) there is no need to check for available space
       
   394       // this folder will be used anyway
       
   395       if ( monthCounter >= KMaxMonthFolders - 1 ) 
       
   396         {
       
   397         PRINT( _L("Camera <> MkDirAll KErrALreadyExists Z9") ) 
       
   398         folderCreated = ETrue;
       
   399         // sanity check to ensure the counter is not too high
       
   400         aMonthCounters[aFolderType] = KMaxMonthFolders - 1;
       
   401         err = KErrNone;
       
   402         }
       
   403       // if this is not the final folder (Z9) check for space and try the next one if necessary
       
   404       else
       
   405         {  
       
   406         PRINT( _L("Camera <> MkDirAll KErrALreadyExists not Z9, retry") )                        
       
   407         CDir* fileList;  
       
   408         TInt dirErr = ( aFs.GetDir( aPath,
       
   409                                     KEntryAttMaskSupported,
       
   410                                     ESortNone,
       
   411                                     fileList ) );  
       
   412         TBool spaceRemaining = EFalse;    
       
   413         if ( !dirErr )
       
   414           {
       
   415           spaceRemaining = ( fileList->Count() + aRequiredFileCount <= KMaxFilesPerFolder );   
       
   416           }
       
   417         delete fileList;  
       
   418         fileList = NULL;                      
       
   419         if ( dirErr )        
       
   420           {
       
   421           PRINT1( _L("Camera <= CCamFolderUtility::DoCreateDestinationFolderL returning %d"), err)   
       
   422           return dirErr;    
       
   423           }             
       
   424                 
       
   425         // If there is insufficient space then try the next folder                                       
       
   426         if ( !spaceRemaining )  
       
   427           {
       
   428           monthCounter++;
       
   429           // Remove the previous counter characters and the trailing backslash then try again                                        
       
   430           aPath.SetLength( aPath.Length() - ( KMultipleFolderNumberChars + 1 ) );
       
   431           }
       
   432         else // This folder has enough space for the capture
       
   433           {
       
   434           folderCreated = ETrue;
       
   435           err = KErrNone;
       
   436           }     
       
   437         }
       
   438       }
       
   439     // There is a problem creating folders - report error         
       
   440     else if ( err )   
       
   441       {
       
   442       PRINT1( _L("Camera <= CCamFolderUtility::DoCreateDestinationFolderL returning %d"), err)
       
   443       return err;    
       
   444       }
       
   445     // A new folder has been created. There is no need to check the space
       
   446     else 
       
   447       {
       
   448       folderCreated = ETrue;
       
   449       }            
       
   450     }
       
   451 
       
   452   PRINT1( _L("Camera <= CCamFolderUtility::DoCreateDestinationFolderL returning %d"), err)
       
   453   return err;        
       
   454   }
       
   455 
       
   456 // ===========================================================================
       
   457 
       
   458 // end of file