camerauis/cameraapp/generic/src/camfolderutility.cpp
changeset 0 1ddebce53859
child 10 8c55c525d5d7
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/camerauis/cameraapp/generic/src/camfolderutility.cpp	Thu Jan 07 16:18:56 2010 +0200
@@ -0,0 +1,432 @@
+/*
+* Copyright (c) 2007-2008 Nokia Corporation and/or its subsidiary(-ies). 
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  
+*
+*  Copyright © 2007-2008 Nokia.  All rights reserved.
+*  This material, including documentation and any related computer
+*  programs, is protected by copyright controlled by Nokia.  All
+*  rights are reserved.  Copying, including reproducing, storing,
+*  adapting or translating, any or all of this material requires the
+*  prior written consent of Nokia.  This material also contains
+*  confidential information which may not be disclosed to others
+*  without the prior written consent of Nokia.
+
+*
+*
+*/
+
+
+// ===========================================================================
+// Included headers
+
+
+#include <bldvariant.hrh> // for feature definitions
+
+#include <f32file.h>
+#include <centralrepository.h>
+#include <pathinfo.h>
+#include <StringLoader.h>
+
+#include <cameraapp.rsg>
+#include <vgacamsettings.rsg>
+
+#include "CamPanic.h"
+#include "CamUtility.h"       // PRINT macros
+#include "CameraappPrivateCRKeys.h"  
+#include "camfolderutility.h"
+
+
+// ===========================================================================
+// Local constants
+
+static const TInt KMultipleFolderNumberChars = 2;
+static const TInt KMaxMonthFolders           = 260;
+static const TInt KBase10                    = 10;
+static const TInt KCamMonthFolderNameLength = 8;
+
+
+_LIT( KCamMonthFolderFormat, "%F%Y%M" );  
+_LIT( KBackslash,            "\\"     );
+_LIT( KCharacterOffset,      "A"      );
+_LIT( KDigitOffset,          "0"      );
+_LIT( KMaxCharacter,         "Z"      );
+_LIT( KWildCardCharacter,    "?"      );
+
+
+
+// ===========================================================================
+// CCamFolderUtility implementation
+
+// ---------------------------------------------------------------------------
+// GetBasePathL
+// Generates the path where new images/videos are to be saved to.
+// ---------------------------------------------------------------------------
+//
+void
+CCamFolderUtility::GetBasePathL( TInt*                 aMonthCounters,
+                                 TInt                  aStorage, // TCamMediaStorage
+                                 TDes&                 aPath, 
+                                 TCamCameraMode aCaptureMode, 
+                                 TBool                 aCreateAll,
+                                 TInt                  aRequiredFileCount,
+                                 TTime                 aTime )
+  {
+  PRINT( _L("Camera => CCamFolderUtility::GetBasePathL"))
+
+  TInt folderTypeIndex = 0;
+  
+    if ( ( aStorage == ECamMediaStoragePhone ) ) // Saving to phone memory
+       { 
+       // phone folders are in the odd indexes
+       folderTypeIndex ++;
+       PRINT( _L("Camera GetBasePathL saving to phone memory"))
+       aPath.Copy( PathInfo::PhoneMemoryRootPath() );
+       }
+       // with multiple drives, mass storage is the default, like phone memory used to be.
+    else if ( aStorage == ECamMediaStorageMassStorage ) // Saving to mass storage memory
+       {
+       PRINT( _L("Camera GetBasePathL saving to mass storage memory"))
+       // Get the root path of the mass storage drive.
+       TInt drive;
+       TInt err = DriveInfo::GetDefaultDrive( DriveInfo::EDefaultMassStorage, drive );
+       TFileName path;
+       err = PathInfo::GetRootPath( path, drive );
+       aPath.Copy(path);
+       }
+    else  // Saving to MMC
+       {
+       PRINT( _L("Camera GetBasePathL saving to memory card"))
+       // Get the root path of the mmc.
+       TInt drive;
+       TInt err = DriveInfo::GetDefaultDrive( DriveInfo::EDefaultRemovableMassStorage, drive );
+       TFileName path;
+       err = PathInfo::GetRootPath( path, drive );
+       aPath.Copy(path);
+       }
+
+     // Append the folder to the path
+  if ( ECamControllerVideo == aCaptureMode )
+      {
+      aPath.Append( PathInfo::VideosPath() );
+      // video folders are offset to ECamFolderTypeVideoMMC
+      folderTypeIndex += ECamFolderTypeVideoMMC;
+      }
+  else 
+      {
+      aPath.Append( PathInfo::ImagesPath() );  
+      }             
+     
+  // Add a folder for the current month
+  // Use the specified time to determine the year and month.
+  // If this is 0 then use the current time.
+  TTime now = aTime;
+  if ( now.Int64() == TInt64( 0 ) )
+      {
+      now.HomeTime();
+      }
+  TBuf<KCamMonthFolderNameLength> monthFolder;
+  now.FormatL( monthFolder, KCamMonthFolderFormat );
+  // If the month folder name is different to the last used month folder name
+  // this indicates that a new month has been started. All the counters will
+  // need to be reinitialised
+  
+  // Get last used folder name
+  TBuf<KCamMonthFolderNameLength> previousMonthFolder;
+  CRepository* cr = CRepository::NewLC( KCRUidCameraappSettings );
+  cr->Get( KCamCrLastUsedMonthFolder, previousMonthFolder );
+  
+  // Compare to current folder name, if different then reset all counters
+  if ( monthFolder.Compare( previousMonthFolder) != 0 )
+      {
+      ResetCounters( aMonthCounters );
+      // Write month folder name to shared data 
+      cr->Set( KCamCrLastUsedMonthFolder, monthFolder );
+      }  
+  CleanupStack::PopAndDestroy( cr );    
+  TBuf<KMaxNameBaseLength> cameraFolder;
+  StringLoader::Load( cameraFolder, R_CAM_CAMERA_SUBFOLDER );
+  aPath.Append( cameraFolder );   
+  aPath.Append( KBackslash );          
+  aPath.Append( monthFolder );  
+  aPath.Append( KBackslash ); 
+  
+  // Keep track of the month folder (YYYYMM) name length
+  // This may be returned e.g.if the month counter destination folder  (YYYYMMXX) is
+  // not created
+  TInt monthFolderLength = aPath.Length();
+  
+  RFs rfs;
+  User::LeaveIfError( rfs.Connect() );
+  CleanupClosePushL( rfs );     
+ 
+  // ensure the path exists
+  TInt err = rfs.MkDirAll( aPath );
+ 
+  // If the folder is newly created then set the counter to 0  
+  if      ( KErrNone          == err ) aMonthCounters[folderTypeIndex] = 0;
+  else if ( KErrAlreadyExists == err ) err = KErrNone;
+  else                                 User::Leave( err );
+
+          
+  // If the month counter is uninitialised it needs to be set up
+  if ( aMonthCounters[folderTypeIndex] < 0 )
+      {
+      User::LeaveIfError( InitialiseMonthCounter( aMonthCounters,
+                                                  aPath,
+                                                  monthFolder,
+                                                  rfs,
+                                                  folderTypeIndex ) );
+      }
+  aPath.Append( monthFolder ); 
+  // Only ensure the folder exists (and has space) if the aCreateAll flag is set
+  if ( aCreateAll )
+      {
+      PRINT( _L("Camera GetBasePathL creating month counter folder") )
+      // This adds on the correct counter if completing without error
+      User::LeaveIfError( CreateDestinationFolder( aMonthCounters,
+                                                   aPath, 
+                                                   rfs, 
+                                                   folderTypeIndex, 
+                                                   aRequiredFileCount ) );
+      }
+  else
+      {
+      TInt monthCounter = aMonthCounters[folderTypeIndex];
+      aPath.Append( KCharacterOffset()[0] + monthCounter/KBase10 );
+      aPath.Append( KDigitOffset()[0] + monthCounter%KBase10 );
+      aPath.Append( KBackslash );
+      // If the folder does not exist then remove the final folder name from the path
+      TEntry entry;
+      if ( rfs.Entry( aPath, entry ) == KErrNotFound )
+          {
+          aPath.SetLength( monthFolderLength );
+          }
+      }        
+  CleanupStack::PopAndDestroy( &rfs );
+
+  PRINT( _L("Camera <= CCamAppController::GetBasePathL returning") )
+  }
+
+
+// ---------------------------------------------------------------------------
+// ResetCounters
+// ---------------------------------------------------------------------------
+//
+void 
+CCamFolderUtility::ResetCounters( TInt* aMonthCounters,
+                                  TInt  aFrom,
+                                  TInt  aTo )
+  {
+  PRINT( _L("Camera => CCamFolderUtility::ResetCounters") )
+    {
+    for( TInt i = aFrom; i <= aTo; i++ )
+      {
+      aMonthCounters[i] = -1;
+      }
+    }
+  }
+
+
+
+// ---------------------------------------------------------------------------
+// InitialiseMonthCounter
+// Sets the value of the folder counter for the current month/media store/mode
+// ---------------------------------------------------------------------------
+//  
+TInt 
+CCamFolderUtility::InitialiseMonthCounter( TInt*  aMonthCounters,
+                                           TDes&  aPath,
+                                           TDesC& aMonthFolder,
+                                           RFs&   aFs,
+                                           TInt   aFolderType )
+  {
+  PRINT( _L("Camera => CCamFolderUtility::InitialiseMonthCounter") )
+
+  // start by initialising the appropriate folder counter to 0
+  aMonthCounters[aFolderType] = 0; 
+      
+  TInt monthFolderLength = aPath.Length();
+  // The month counter folder starts with the same characters as the parent month folder
+  aPath.Append( aMonthFolder );  
+  TInt charCount;
+  // Add on '??' wildcard characters to get a list of all folders with this 
+  // month's format
+  for ( charCount = 0; charCount < KMultipleFolderNumberChars; charCount++ )
+      {
+      aPath.Append( KWildCardCharacter );
+      }
+  // Get a list of folders for this month, sorted in descending alphabetical order
+  // the first entry should be the latest used folder
+  CDir* dirList;
+  TInt err = KErrNone;
+  err =  aFs.GetDir( aPath,
+                     KEntryAttMatchExclusive|KEntryAttDir,
+                     ESortByName|EDescending,
+                     dirList );
+  // Prune back to the parent folder path                           
+  aPath.SetLength( monthFolderLength );                           
+  if ( err == KErrNone )                           
+    {
+    TInt monthFolderCount = dirList->Count();                
+    TInt index = 0;
+    TBool done = EFalse;
+    // Look through the list of folders in the month for the highest numbered folder
+    // with the format YYYYMMAX Where YYYY is the year MM is the month A is an alphabetical
+    // character in the range a-z or A-Z and X is a digit 0-9
+    while ( index < monthFolderCount && !done )
+      {
+      done = ETrue;
+      // The list is sorted in descending order. Get the last 2 characters from
+      // the first directory in the list these indicate the highest folder number
+      TPtrC name = ( *dirList )[index].iName; 
+      TInt nameLength = name.Length();
+      // Check the first character is in the range a-z or A-Z
+      TChar firstChar = name[nameLength - KMultipleFolderNumberChars];
+      firstChar.UpperCase();
+      // If the character is not in the range then disregard this folder
+      if ( firstChar < KCharacterOffset()[0] ||
+           firstChar > KMaxCharacter()[0] )
+        {
+        done = EFalse;
+        }
+      // Check the second character is in the range 0-9                
+      TChar secondChar = name[nameLength - 1];
+      TInt secondCharVal = secondChar.GetNumericValue();
+      if ( secondCharVal < 0 ||
+           secondCharVal > KBase10 - 1 )
+        {
+        done = EFalse;
+        }   
+      if ( done )                             
+        {
+        TUint folderNumber = firstChar;
+        // 10's part of folder number is represented by characters A-Z
+        // convert the character into a decimal value
+        folderNumber -= KCharacterOffset()[0];
+        folderNumber *= KBase10; 
+        // Now add on the units
+        folderNumber += secondCharVal;
+        aMonthCounters[aFolderType] = folderNumber;
+        }
+      // TUint folderNumber = name[nameLength - 2];       
+      index++;   
+      } 
+    }
+  delete dirList;  
+  dirList = NULL;     
+
+  PRINT1( _L("Camera <= CCamAppController::InitialiseMonthCounter returning %d"), err)
+  return err;      
+  }
+  
+// ---------------------------------------------------------------------------
+// CreateDestinationFolder
+// Creates the folder where new images/videos are to be saved to.
+// ---------------------------------------------------------------------------
+//
+TInt 
+CCamFolderUtility::CreateDestinationFolder( TInt* aMonthCounters,
+                                            TDes& aPath,
+                                            RFs&  aFs, 
+                                            TInt  aFolderType,
+                                            TInt  aRequiredFileCount )    
+  {
+  PRINT( _L("Camera => CCamFolderUtility::CreateDestinationFolder ") ) 
+  __ASSERT_DEBUG( aFolderType < ECamFolderTypeLast, CamPanic( ECamPanicBadIndex ) );
+
+  TInt folderCreated = EFalse;
+  // This error value will only be retained if the counter is outside
+  // the allowed range 
+  TInt err = KErrArgument; 
+  TInt monthCounter = aMonthCounters[aFolderType];
+  while ( !folderCreated && monthCounter < KMaxMonthFolders )
+    {
+    aMonthCounters[aFolderType] = monthCounter;
+    err = KErrNone;   
+    // Add on the new counter
+    aPath.Append( KCharacterOffset()[0] + monthCounter/KBase10 );
+    aPath.Append( KDigitOffset()[0] + monthCounter%KBase10 );
+    aPath.Append( KBackslash );
+    err = aFs.MkDirAll( aPath );
+    PRINT1( _L("Camera <> MkDirAll returned %d "), err ) 
+    // If the folder already exists then check there is enough space for the required file count
+    if ( err == KErrAlreadyExists )
+      {
+      PRINT( _L("Camera <> MkDirAll KErrALreadyExists ") ) 
+      // if this is the final folder (Z9) there is no need to check for available space
+      // this folder will be used anyway
+      if ( monthCounter >= KMaxMonthFolders - 1 ) 
+        {
+        PRINT( _L("Camera <> MkDirAll KErrALreadyExists Z9") ) 
+        folderCreated = ETrue;
+        // sanity check to ensure the counter is not too high
+        aMonthCounters[aFolderType] = KMaxMonthFolders - 1;
+        err = KErrNone;
+        }
+      // if this is not the final folder (Z9) check for space and try the next one if necessary
+      else
+        {  
+        PRINT( _L("Camera <> MkDirAll KErrALreadyExists not Z9, retry") )                        
+        CDir* fileList;  
+        TInt dirErr = ( aFs.GetDir( aPath,
+                                    KEntryAttMaskSupported,
+                                    ESortNone,
+                                    fileList ) );  
+        TBool spaceRemaining = EFalse;    
+        if ( !dirErr )
+          {
+          spaceRemaining = ( fileList->Count() + aRequiredFileCount <= KMaxFilesPerFolder );   
+          }
+        delete fileList;  
+        fileList = NULL;                      
+        if ( dirErr )        
+          {
+          PRINT1( _L("Camera <= CCamFolderUtility::DoCreateDestinationFolderL returning %d"), err)   
+          return dirErr;    
+          }             
+                
+        // If there is insufficient space then try the next folder                                       
+        if ( !spaceRemaining )  
+          {
+          monthCounter++;
+          // Remove the previous counter characters and the trailing backslash then try again                                        
+          aPath.SetLength( aPath.Length() - ( KMultipleFolderNumberChars + 1 ) );
+          }
+        else // This folder has enough space for the capture
+          {
+          folderCreated = ETrue;
+          err = KErrNone;
+          }     
+        }
+      }
+    // There is a problem creating folders - report error         
+    else if ( err )   
+      {
+      PRINT1( _L("Camera <= CCamFolderUtility::DoCreateDestinationFolderL returning %d"), err)
+      return err;    
+      }
+    // A new folder has been created. There is no need to check the space
+    else 
+      {
+      folderCreated = ETrue;
+      }            
+    }
+
+  PRINT1( _L("Camera <= CCamFolderUtility::DoCreateDestinationFolderL returning %d"), err)
+  return err;        
+  }
+
+// ===========================================================================
+
+// end of file