|
1 /* |
|
2 * Copyright (c) 2009-2010 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 */ |
|
17 #include <pathinfo.h> |
|
18 #include <pathconfiguration.hrh> |
|
19 #include <coemain.h> // For CCoeEnv |
|
20 #include <QDate> |
|
21 |
|
22 #include "cxefilenamegeneratorsymbian.h" |
|
23 #include "cxeengine.h" |
|
24 #include "cxenamespace.h" |
|
25 #include "cxutils.h" |
|
26 #include "cxesysutil.h" |
|
27 #include "cxesettings.h" |
|
28 #include "cxeerror.h" |
|
29 #include "cxeerrormappingsymbian.h" |
|
30 |
|
31 #include "OstTraceDefinitions.h" |
|
32 #ifdef OST_TRACE_COMPILER_IN_USE |
|
33 #include "cxefilenamegeneratorsymbianTraces.h" |
|
34 #endif |
|
35 |
|
36 |
|
37 using namespace Cxe; |
|
38 |
|
39 // =========================================================================== |
|
40 // Local constants |
|
41 |
|
42 static const int KMultipleFolderNumberChars = 2; |
|
43 static const int KMaxMonthFolders = 260; |
|
44 static const int KBase10 = 10; |
|
45 static const int KMaxFilesPerFolder = 100; |
|
46 |
|
47 const char* CAMERA_FOLDER = "Camera"; |
|
48 const char* FOLDER_SEPARATOR = "\\"; |
|
49 const char* WILDCARD_CHARACTER = "?"; |
|
50 |
|
51 const char CHAR_OFFSET = 'A'; |
|
52 const char DIGIT_OFFSET = '0'; |
|
53 const char MAX_CHAR = 'Z'; |
|
54 |
|
55 const TInt64 KMinRequiredSpaceImage = 2000000; |
|
56 |
|
57 // Whether there's enough space for video or not is handled lower in the SW stack |
|
58 // so this is set to 0 to fix an error |
|
59 const TInt64 KMinRequiredSpaceVideo = 0; |
|
60 |
|
61 |
|
62 |
|
63 // =========================================================================== |
|
64 // Local functions |
|
65 |
|
66 /** |
|
67 * Convert QString to TPtrC16. |
|
68 */ |
|
69 inline TPtrC16 convertToTPtrC16(const QString& string) |
|
70 { |
|
71 return TPtrC16(reinterpret_cast<const TUint16*>(string.utf16())); |
|
72 } |
|
73 |
|
74 |
|
75 // =========================================================================== |
|
76 // Class functions |
|
77 |
|
78 /** |
|
79 * Constructor |
|
80 */ |
|
81 CxeFilenameGeneratorSymbian::CxeFilenameGeneratorSymbian(CxeSettings &settings, CameraMode mode) |
|
82 : mFs(CCoeEnv::Static()->FsSession()), |
|
83 mSettings(settings), |
|
84 mCurrentMode(mode) |
|
85 { |
|
86 CX_DEBUG_ENTER_FUNCTION(); |
|
87 OstTrace0(camerax_performance, CXEFILENAMEGENERATOR_1, "msg: e_CX_FILENAMEGENERATOR_NEW 1"); |
|
88 |
|
89 // Set default values (used in case of error retrieving values) |
|
90 mCurrentMonth = ""; |
|
91 mMonthCounterImage = -1; |
|
92 mMonthCounterVideo = -1; |
|
93 mImageCounter = 0; |
|
94 mVideoCounter = 0; |
|
95 |
|
96 // Retrieve last used counter values from settings |
|
97 mCurrentMonth = mSettings.get<QString>(CxeSettingIds::FNAME_MONTH_FOLDER, ""); |
|
98 mImageCounter = mSettings.get<int>(CxeSettingIds::FNAME_IMAGE_COUNTER, 0); |
|
99 mVideoCounter = mSettings.get<int>(CxeSettingIds::FNAME_VIDEO_COUNTER, 0); |
|
100 |
|
101 OstTrace0(camerax_performance, CXEFILENAMEGENERATOR_2, "msg: e_CX_FILENAMEGENERATOR_NEW 0"); |
|
102 CX_DEBUG_EXIT_FUNCTION(); |
|
103 } |
|
104 |
|
105 /** |
|
106 * Destructor |
|
107 */ |
|
108 CxeFilenameGeneratorSymbian::~CxeFilenameGeneratorSymbian() |
|
109 { |
|
110 CX_DEBUG_ENTER_FUNCTION(); |
|
111 |
|
112 CX_DEBUG_EXIT_FUNCTION(); |
|
113 } |
|
114 |
|
115 /** |
|
116 * This must be called for every burst capture. |
|
117 */ |
|
118 void CxeFilenameGeneratorSymbian::startNewImageFilenameSequence() |
|
119 { |
|
120 CX_DEBUG_ENTER_FUNCTION(); |
|
121 |
|
122 /* NOTES |
|
123 When the client calls this function, we should start a new "sequence" of filenames... |
|
124 What I mean here is that for burst capture, we have filename sequences like... |
|
125 Filename1 |
|
126 Filename1(002) |
|
127 Filename1(003) |
|
128 and so on... |
|
129 |
|
130 So this function says "Ok, I'm starting a new capture sequence here... so reset your variables" |
|
131 This should be done below... |
|
132 Development efforts need to be aware of Edrive vs. Cdrive, and also multiple drive support. |
|
133 */ |
|
134 |
|
135 CX_DEBUG_EXIT_FUNCTION(); |
|
136 } |
|
137 |
|
138 /** |
|
139 * Generates the next file name in the sequence. |
|
140 * @param filename: A QString reference to hold the filename |
|
141 * @return error id, Id::None if no error |
|
142 */ |
|
143 CxeError::Id CxeFilenameGeneratorSymbian::nextImageFilenameInSequence(QString &qfName, const QString &fileExt) |
|
144 { |
|
145 CX_DEBUG_IN_FUNCTION(); |
|
146 |
|
147 /** @todo: When the client calls this function, the next filename in the |
|
148 * sequence is retrieved. The entire path should be included... e.g |
|
149 * C//PHOTOS//SOMETHING//HELLO//Filename001.jpg |
|
150 */ |
|
151 return generateFilename(qfName, fileExt); |
|
152 } |
|
153 |
|
154 /** |
|
155 * Generates image/video file name depending on the current active mode. |
|
156 * @param filename: A QString reference to hold the filename |
|
157 * @return error id, CxeError::None if no error. |
|
158 */ |
|
159 CxeError::Id CxeFilenameGeneratorSymbian::generateFilename(QString &qfName, const QString &fileExt) |
|
160 { |
|
161 CX_DEBUG_ENTER_FUNCTION(); |
|
162 OstTrace0(camerax_performance, CXEFILENAMEGENERATORSYMBIAN_GENERATENAME_1, "msg: e_CX_GENERATE_FILENAME 1"); |
|
163 |
|
164 // Make sure that the path for images/videos exists |
|
165 QString path; |
|
166 int err = selectFolder(path); |
|
167 |
|
168 // Continue generating filename, if no errors encountered yet |
|
169 if (!err) { |
|
170 // Generate and append the file name to construct the full path |
|
171 QString fileName; |
|
172 err = generateUniqueFileName(path, fileName, fileExt); |
|
173 if (!err) { |
|
174 qfName = path + fileName; |
|
175 } |
|
176 } |
|
177 |
|
178 OstTrace0(camerax_performance, CXEFILENAMEGENERATORSYMBIAN_GENERATENAME_2, "msg: e_CX_GENERATE_FILENAME 0"); |
|
179 CX_DEBUG_EXIT_FUNCTION(); |
|
180 return CxeErrorHandlingSymbian::map(err); |
|
181 } |
|
182 |
|
183 /** |
|
184 * Generates a unique file name in the given path. |
|
185 * @param filePath Path for the file (reference) |
|
186 * @param fileName Name of the file (reference) |
|
187 * @return Symbian error code (used internally) |
|
188 */ |
|
189 int CxeFilenameGeneratorSymbian::generateUniqueFileName(QString &filePath, QString &fileName, const QString &ext) |
|
190 { |
|
191 CX_DEBUG_ENTER_FUNCTION(); |
|
192 |
|
193 // At this point the path must exist. |
|
194 // Remote possibility / security threat that it doesn't exist or is not a folder. |
|
195 TEntry entry; |
|
196 int ferr = mFs.Entry(convertToTPtrC16(filePath), entry); |
|
197 if (ferr != KErrNone || !entry.IsDir()) { |
|
198 return ferr; |
|
199 } |
|
200 |
|
201 // Initialize counters and file extension |
|
202 int *fileCounter = &mImageCounter; |
|
203 |
|
204 if (mCurrentMode==VideoMode) { |
|
205 fileCounter = &mVideoCounter; |
|
206 } |
|
207 |
|
208 QString fnFormat("%1%2%3"); |
|
209 QString number; |
|
210 |
|
211 // get the file name suffix |
|
212 QString baseFileName; |
|
213 mSettings.get(CxeSettingIds::FNAME_FOLDER_SUFFIX, baseFileName); |
|
214 |
|
215 while (true) { |
|
216 // Generate new name |
|
217 number = number.sprintf("%04d", *fileCounter); |
|
218 fileName = fnFormat.arg(number, baseFileName, ext); |
|
219 |
|
220 CX_DEBUG(("Checking filename [%s]", fileName.toAscii().constData())); |
|
221 |
|
222 // Check if it exists |
|
223 ferr = checkExistence(filePath + fileName); |
|
224 if (ferr == KErrNone) { |
|
225 // Filename has already been used in this location, try the next number |
|
226 CX_DEBUG(("File exists already")); |
|
227 (*fileCounter)++; |
|
228 } else if (ferr == KErrNotFound) { |
|
229 // No file with this name, use it. |
|
230 CX_DEBUG(("Filename free, using it")); |
|
231 ferr = KErrNone; |
|
232 break; |
|
233 } else { |
|
234 // Filename could not be reserved. Log actual error and report as general error. |
|
235 CX_DEBUG(("[WARNING] Error %d generating filename!", ferr)); |
|
236 ferr = KErrGeneral; |
|
237 break; |
|
238 } |
|
239 } |
|
240 |
|
241 // Increment counter if image mode. Video counter is incremented when |
|
242 // video has been actually recorded |
|
243 if (mCurrentMode == ImageMode) { |
|
244 raiseCounterValue(); |
|
245 } |
|
246 |
|
247 CX_DEBUG_EXIT_FUNCTION(); |
|
248 return ferr; |
|
249 } |
|
250 |
|
251 /** |
|
252 * Computes the suffix to be used in destination folder name. |
|
253 */ |
|
254 void CxeFilenameGeneratorSymbian::computeFolderSuffix(int folderNumber, QString &suffix) |
|
255 { |
|
256 CX_DEBUG_ENTER_FUNCTION(); |
|
257 |
|
258 // Clear any old content. |
|
259 suffix = ""; |
|
260 |
|
261 // Example: |
|
262 // if folderNumber is 15 |
|
263 // 15/10 = 1 (int) |
|
264 // A + 1 = B |
|
265 suffix += (CHAR_OFFSET + folderNumber/KBase10); |
|
266 // 15%10 = 5 |
|
267 // 0 + 5 = 5 |
|
268 // => suffix = B5 |
|
269 suffix += (DIGIT_OFFSET + folderNumber%KBase10); |
|
270 CX_DEBUG_EXIT_FUNCTION(); |
|
271 } |
|
272 |
|
273 /** |
|
274 * Compute the month counter value (0 to 259 => A0 to Z9). |
|
275 * @param |
|
276 * @return Symbian error code (internal to class) |
|
277 */ |
|
278 int CxeFilenameGeneratorSymbian::computeMonthCounter(QString &path, QString& monthFolder, int &monthCounter) |
|
279 { |
|
280 CX_DEBUG_ENTER_FUNCTION(); |
|
281 bool done = false; |
|
282 |
|
283 // Query the month folder: path\YYYYMM?? |
|
284 QString queryPath = path + monthFolder; |
|
285 for (int charCount = 0; charCount < KMultipleFolderNumberChars; charCount++) { |
|
286 queryPath += WILDCARD_CHARACTER; |
|
287 } |
|
288 CX_DEBUG(("Listing folders with wildcards: [%s]", queryPath.toAscii().constData())); |
|
289 |
|
290 // Get a list of folders for this month, sorted in descending alphabetical order. |
|
291 // The first entry should be the latest used folder. |
|
292 CDir* dirList; |
|
293 int err = mFs.GetDir(convertToTPtrC16(queryPath), |
|
294 KEntryAttMatchExclusive|KEntryAttDir, |
|
295 ESortByName|EDescending, |
|
296 dirList); |
|
297 |
|
298 // On errors (or empty list of folders), let's default to zero. |
|
299 // Errors here should be recoverable when we start to |
|
300 // count files within current directory. |
|
301 monthCounter = 0; |
|
302 |
|
303 // If directory listing worked fine, then figure out the last month folder number |
|
304 if (err == KErrNone) { |
|
305 int monthFolderCount = dirList->Count(); |
|
306 CX_DEBUG(("Matching folder count: %d", monthFolderCount)); |
|
307 int index = 0; |
|
308 // Look through the list of folders in the month for the highest numbered folder |
|
309 // with the format YYYYMMAX Where YYYY is the year MM is the month A is an alphabetical |
|
310 // character in the range a-z or A-Z and X is a digit 0-9 |
|
311 while ( index < monthFolderCount && !done ) { |
|
312 // The list is sorted in descending order. Get the last 2 characters from |
|
313 // the first directory in the list these indicate the highest folder number |
|
314 TPtrC name = ( *dirList )[index].iName; |
|
315 int nameLength = name.Length(); |
|
316 |
|
317 // Check the first character is in the range a-z or A-Z |
|
318 // and the second character is in the range 0-9 |
|
319 TChar firstChar = name[nameLength - KMultipleFolderNumberChars]; |
|
320 firstChar.UpperCase(); |
|
321 TChar secondChar = name[nameLength - 1]; |
|
322 int secondCharVal = secondChar.GetNumericValue(); |
|
323 |
|
324 // If 1st character is NOT in the range(A-Z) then disregard this folder |
|
325 if (firstChar < CHAR_OFFSET || firstChar > MAX_CHAR) { |
|
326 done = false; |
|
327 } |
|
328 // If 2nd character is NOT in the range(0-9) then disregard this folder |
|
329 else if (secondCharVal < 0 || secondCharVal > KBase10-1) { |
|
330 done = false; |
|
331 } |
|
332 else { |
|
333 done = true; |
|
334 } |
|
335 |
|
336 // If no problems were encountered, then calculate the folder number |
|
337 if (done) { |
|
338 // 10's part of folder number is represented by characters A-Z |
|
339 // convert the character into a decimal value (*10) and add on the units. |
|
340 monthCounter = ((int)firstChar-(int)CHAR_OFFSET)*KBase10 + secondCharVal; |
|
341 CX_DEBUG(("Calculated month counter value: %d", monthCounter)); |
|
342 // Make sure that month counter doesn't exceed Z9 |
|
343 if (monthCounter >= KMaxMonthFolders) { |
|
344 monthCounter = KMaxMonthFolders - 1; |
|
345 } |
|
346 } |
|
347 index++; |
|
348 } |
|
349 } else { |
|
350 CX_DEBUG(("[WARNING] Error %d listing month folders!", err)); |
|
351 } |
|
352 |
|
353 delete dirList; |
|
354 CX_DEBUG_EXIT_FUNCTION(); |
|
355 return err; |
|
356 } |
|
357 |
|
358 /** |
|
359 * Checks that the month folder exists: creates the folder if required. |
|
360 * Returns error code if the folder can't be created. |
|
361 */ |
|
362 int CxeFilenameGeneratorSymbian::selectFolder(QString &suggestedPath) |
|
363 { |
|
364 CX_DEBUG_ENTER_FUNCTION(); |
|
365 OstTrace0(camerax_performance, CXEFILENAMEGENERATORSYMBIAN_SELECTFOLDER_1, "msg: e_CX_SELECT_FOLDER 1"); |
|
366 |
|
367 // Compose the path string and select counter based on mode. |
|
368 QString basePath = "%1%2\\"; |
|
369 int *monthCounter = &mMonthCounterImage; |
|
370 |
|
371 if (ImageMode == mCurrentMode) { |
|
372 basePath = basePath.arg(mImagesPath, mCurrentMonth); |
|
373 } |
|
374 else { // VideoMode |
|
375 basePath = basePath.arg(mVideosPath, mCurrentMonth); |
|
376 monthCounter = &mMonthCounterVideo; |
|
377 } |
|
378 CX_DEBUG(("Base path [%s]", basePath.toAscii().constData())); |
|
379 |
|
380 QString suffix; |
|
381 QString newPath; |
|
382 int status(KErrNone); |
|
383 bool created(false); |
|
384 |
|
385 while (true) { |
|
386 // Construct the complete path |
|
387 computeFolderSuffix(*monthCounter, suffix); |
|
388 newPath = basePath + mCurrentMonth + suffix + FOLDER_SEPARATOR; |
|
389 |
|
390 // Check if the folder exists, and create if not. |
|
391 CX_DEBUG(("Checking new path [%s] ..", newPath.toAscii().constData())); |
|
392 status = ensureExists(newPath, created); |
|
393 |
|
394 // Check if the folder can be used. |
|
395 if (status == KErrNone) { |
|
396 // If the folder was newly created, it's empty and can be used. |
|
397 // If the folder is last available month folder, |
|
398 // we need to use it even if it has "too many" files. |
|
399 if (created || *monthCounter >= (KMaxMonthFolders-1)) { |
|
400 CX_DEBUG(("Newly created folder, or the last month folder available, using it")); |
|
401 suggestedPath = newPath; |
|
402 break; |
|
403 } else { |
|
404 // For other folders, if the folder already exists then make sure |
|
405 // that it doesn't contain maximum number of files already. |
|
406 CX_DEBUG(("Folder already existed, check the amount of files..")); |
|
407 CDir* fileList; |
|
408 status = mFs.GetDir(convertToTPtrC16(newPath), |
|
409 KEntryAttMaskSupported, |
|
410 ESortNone, |
|
411 fileList); |
|
412 CX_DEBUG(("Folder contains %d files", fileList->Count())); |
|
413 |
|
414 bool spaceRemaining(fileList->Count() < KMaxFilesPerFolder); |
|
415 |
|
416 delete fileList; |
|
417 fileList = NULL; |
|
418 |
|
419 if (status == KErrNone && spaceRemaining) { |
|
420 // Not too many files on the folder, use it. |
|
421 CX_DEBUG(("File count acceptable, using this folder")); |
|
422 suggestedPath = newPath; |
|
423 break; |
|
424 } else { |
|
425 // Need to check the next folder, this one is full, |
|
426 // or we had error listing it's contents. |
|
427 CX_DEBUG(("Folder full, continue search")); |
|
428 (*monthCounter)++; |
|
429 } |
|
430 } |
|
431 } else { |
|
432 // Unknown error encountered. |
|
433 // LOG the error and use the basePath! |
|
434 // Base path's existence has been checked when init was called. |
|
435 CX_DEBUG(("[WARNING] - error %d encountered. Using base path as fallback.", status)); |
|
436 suggestedPath = basePath; |
|
437 break; |
|
438 } |
|
439 } |
|
440 |
|
441 OstTrace0(camerax_performance, CXEFILENAMEGENERATORSYMBIAN_SELECTFOLDER_2, "msg: e_CX_SELECT_FOLDER 0"); |
|
442 CX_DEBUG_EXIT_FUNCTION(); |
|
443 |
|
444 // We fallback to basePath in case of unknown errors, |
|
445 // so no error will be reported here. |
|
446 return KErrNone; |
|
447 } |
|
448 |
|
449 |
|
450 |
|
451 /** |
|
452 * Initializes the month folders. |
|
453 * @return Symbian error code (internal to class) |
|
454 */ |
|
455 int CxeFilenameGeneratorSymbian::initMonthFolders() |
|
456 { |
|
457 CX_DEBUG_ENTER_FUNCTION(); |
|
458 OstTrace0(camerax_performance, CXEFILENAMEGENERATORSYMBIAN_INITFOLDERS_1, "msg: e_CX_INIT_MONTH_FOLDER 1"); |
|
459 |
|
460 // Month folder: YYYYMM, with suffix: YYYYMMXX |
|
461 QString monthFolder = QDate::currentDate().toString("yyyyMM"); |
|
462 |
|
463 // If the month folder name is different from the last used month folder name |
|
464 // this indicates that a new month has been started. |
|
465 if ( monthFolder.compare(mCurrentMonth) != 0 ) { |
|
466 resetCounters(monthFolder); |
|
467 } |
|
468 |
|
469 // Check/create that the month folder exists |
|
470 int *monthCounter = &mMonthCounterImage; |
|
471 QString path = "%1%2\\"; |
|
472 if (ImageMode==mCurrentMode) { |
|
473 path = path.arg(mImagesPath, monthFolder); |
|
474 } |
|
475 else { |
|
476 path = path.arg(mVideosPath, monthFolder); |
|
477 monthCounter = &mMonthCounterVideo; |
|
478 } |
|
479 |
|
480 CX_DEBUG(("Check if exists, create if not [%s]", path.toAscii().constData())); |
|
481 bool created(false); |
|
482 int status(ensureExists(path, created)); |
|
483 |
|
484 if (status == KErrNone) { |
|
485 if (created) { |
|
486 // New folder, new month -> counter starts from zero. |
|
487 *monthCounter = 0; |
|
488 } else { |
|
489 // If the month counter is un-initialised it needs to be set up. |
|
490 if (*monthCounter < 0) { |
|
491 status = computeMonthCounter(path, monthFolder, *monthCounter); |
|
492 if (status != KErrNone) { |
|
493 CX_DEBUG(("[WARNING] - Error setting month counter: %d", status)); |
|
494 *monthCounter = 0; |
|
495 } |
|
496 } |
|
497 } |
|
498 } else { |
|
499 //! @todo: Review error handling |
|
500 // Report error - can't continue without 'camera' and camera\YYYYMM folders |
|
501 CX_DEBUG(("[FATAL] - Could not create month folder, error %d", status)); |
|
502 } |
|
503 |
|
504 OstTrace0(camerax_performance, CXEFILENAMEGENERATORSYMBIAN_INITFOLDERS_2, "msg: e_CX_INIT_MONTH_FOLDER 0"); |
|
505 CX_DEBUG_EXIT_FUNCTION(); |
|
506 return status; |
|
507 } |
|
508 |
|
509 /** |
|
510 * Checks if the passed amount of disk space is available on the passed drive. |
|
511 * @return true if space available, false otherwise |
|
512 */ |
|
513 bool CxeFilenameGeneratorSymbian::spaceAvailable(int &driveIndex, TInt64 minSpaceInBytes) |
|
514 { |
|
515 CX_DEBUG_ENTER_FUNCTION(); |
|
516 |
|
517 TVolumeInfo vInfo; |
|
518 |
|
519 // Get the drive/volume details |
|
520 int status(KErrNone); |
|
521 driveIndex = CxeSysUtil::getCameraDrive(mFs); |
|
522 if (driveIndex >= 0) { |
|
523 status = mFs.Volume(vInfo, driveIndex); |
|
524 } |
|
525 |
|
526 CX_DEBUG_EXIT_FUNCTION(); |
|
527 return (status == KErrNone) ? vInfo.iFree >= minSpaceInBytes : false; |
|
528 |
|
529 } |
|
530 |
|
531 /** |
|
532 * Selects the drive to use based on preference and availability. |
|
533 * @param index of the drive to be used (reference) |
|
534 * @return Symbian error code (internal to class) |
|
535 */ |
|
536 int CxeFilenameGeneratorSymbian::selectDrive(int &drive) |
|
537 { |
|
538 CX_DEBUG_ENTER_FUNCTION(); |
|
539 int err = KErrNone; |
|
540 TInt64 minDiskSpace = KMinRequiredSpaceImage; |
|
541 |
|
542 if (Cxe::VideoMode == mCurrentMode) { |
|
543 minDiskSpace = KMinRequiredSpaceVideo; |
|
544 } |
|
545 |
|
546 // Check the available space. |
|
547 // Drive index is set here also. |
|
548 if ( !spaceAvailable(drive, minDiskSpace)) { |
|
549 // All drives are full or inaccessible |
|
550 err = KErrDiskFull; |
|
551 } |
|
552 |
|
553 CX_DEBUG_EXIT_FUNCTION(); |
|
554 return err; |
|
555 } |
|
556 |
|
557 /** |
|
558 * Initializes the value of base path for the given mode and drive. |
|
559 */ |
|
560 void CxeFilenameGeneratorSymbian::initBasePath(QString &path, int drive) |
|
561 { |
|
562 CX_DEBUG_ENTER_FUNCTION(); |
|
563 |
|
564 // Get the root path for the given drive. |
|
565 TFileName tPath; |
|
566 PathInfo::GetRootPath(tPath, drive); |
|
567 |
|
568 if (VideoMode == mCurrentMode) { |
|
569 tPath.Append( PathInfo::VideosPath() ); |
|
570 } |
|
571 else { |
|
572 tPath.Append( PathInfo::ImagesPath() ); |
|
573 } |
|
574 |
|
575 //! @todo: Fetch localized Camera folder name, if/when applicable. |
|
576 path = QString::fromUtf16(tPath.Ptr(), tPath.Length()); |
|
577 path = path + CAMERA_FOLDER + FOLDER_SEPARATOR; |
|
578 |
|
579 CX_DEBUG(("Path: %s", path.toAscii().constData())); |
|
580 CX_DEBUG_EXIT_FUNCTION(); |
|
581 } |
|
582 |
|
583 /** |
|
584 * Resets the image and video counters used for file name generation. |
|
585 */ |
|
586 void CxeFilenameGeneratorSymbian::resetCounters(QString &monthFolder) |
|
587 { |
|
588 CX_DEBUG_ENTER_FUNCTION(); |
|
589 |
|
590 mCurrentMonth = monthFolder; |
|
591 mMonthCounterImage = 0; |
|
592 mMonthCounterVideo = 0; |
|
593 |
|
594 // Save the setting values |
|
595 // Errors (if any) encountered here are not handled, since these indicate |
|
596 // that settings are'nt saved. If settings are not fetched next time, |
|
597 // then default settings are used. |
|
598 mSettings.set(CxeSettingIds::FNAME_MONTH_FOLDER, mCurrentMonth); |
|
599 |
|
600 CX_DEBUG_EXIT_FUNCTION(); |
|
601 } |
|
602 |
|
603 /** |
|
604 * Initializes the base folder names and counters |
|
605 * NB: Video mode init requires file name. So this should be called |
|
606 * before init is called for image/video capture controls. |
|
607 * Initializes only for appropriate mode (image/video). |
|
608 */ |
|
609 CxeError::Id CxeFilenameGeneratorSymbian::init(Cxe::CameraMode mode) |
|
610 { |
|
611 CX_DEBUG_ENTER_FUNCTION(); |
|
612 OstTrace0(camerax_performance, CXEFILENAMEGENERATORSYMBIAN_INIT_1, "msg: e_CX_FILENAMEGENERATOR_INIT 1"); |
|
613 |
|
614 mCurrentMode = mode; |
|
615 int err = KErrNone; |
|
616 bool initialized = (mode==ImageMode && !mImagesPath.isEmpty()) || |
|
617 (mode==VideoMode && !mVideosPath.isEmpty()); |
|
618 |
|
619 if (!initialized) { |
|
620 // Select a drive based on available disk space |
|
621 int drive; |
|
622 err = selectDrive(drive); |
|
623 if (!err) { |
|
624 if (mode == ImageMode) { |
|
625 initBasePath(mImagesPath, drive); |
|
626 } |
|
627 else { |
|
628 initBasePath(mVideosPath, drive); |
|
629 } |
|
630 |
|
631 // Initialize the month folders and counters so that |
|
632 // file names can be generated quickly when requested. |
|
633 err = initMonthFolders(); |
|
634 } |
|
635 } |
|
636 |
|
637 OstTrace0(camerax_performance, CXEFILENAMEGENERATORSYMBIAN_INIT_2, "msg: e_CX_FILENAMEGENERATOR_INIT 0"); |
|
638 CX_DEBUG_EXIT_FUNCTION(); |
|
639 return CxeErrorHandlingSymbian::map(err); |
|
640 } |
|
641 |
|
642 /** |
|
643 * Raises file name counter value by one |
|
644 */ |
|
645 void CxeFilenameGeneratorSymbian::raiseCounterValue() |
|
646 { |
|
647 if (VideoMode==mCurrentMode) { |
|
648 mSettings.set(CxeSettingIds::FNAME_VIDEO_COUNTER, ++mVideoCounter); |
|
649 } |
|
650 else { |
|
651 mSettings.set(CxeSettingIds::FNAME_IMAGE_COUNTER, ++mImageCounter); |
|
652 } |
|
653 } |
|
654 |
|
655 /** |
|
656 * Check if the given file or directory exists. |
|
657 * @return KErrNone, if given file/directory exists, KErrNotFound if not. |
|
658 * Other Symbian error code on "real" errors. |
|
659 */ |
|
660 int CxeFilenameGeneratorSymbian::checkExistence(const QString& path) |
|
661 { |
|
662 CX_DEBUG_ENTER_FUNCTION(); |
|
663 |
|
664 unsigned int placeHolder(0); |
|
665 int status(mFs.Att(convertToTPtrC16(path), placeHolder)); |
|
666 |
|
667 CX_DEBUG_EXIT_FUNCTION(); |
|
668 return status; |
|
669 } |
|
670 |
|
671 |
|
672 /** |
|
673 * Check if directory exists and create if not. |
|
674 * @param created When returned, holds if the folder needed to be created or not. |
|
675 * @return KErrNone, if folder existed or was created successfully. |
|
676 * Other Symbian error code if there were errors. |
|
677 */ |
|
678 int CxeFilenameGeneratorSymbian::ensureExists(const QString& path, bool& created) |
|
679 { |
|
680 CX_DEBUG_ENTER_FUNCTION(); |
|
681 |
|
682 // Default to "not created" if errors are encountered. |
|
683 created = false; |
|
684 |
|
685 unsigned int placeHolder(0); |
|
686 TPtrC16 pathDesc(convertToTPtrC16(path)); |
|
687 CX_DEBUG_SYMBIAN((_L("Checking [%S]"), &pathDesc)); |
|
688 |
|
689 // Check if it already exists |
|
690 CX_DEBUG(("CxeFilenameGeneratorSymbian::ensureExists - check existence..")); |
|
691 int status = mFs.Att(pathDesc, placeHolder); |
|
692 CX_DEBUG(("CxeFilenameGeneratorSymbian::ensureExists - ..check existence")); |
|
693 |
|
694 if( status == KErrPathNotFound || status == KErrNotFound ) { |
|
695 // Create path if doesn't exist yet. |
|
696 CX_DEBUG(("CxeFilenameGeneratorSymbian::ensureExists - create path..")); |
|
697 status = mFs.MkDirAll(pathDesc); |
|
698 CX_DEBUG(("CxeFilenameGeneratorSymbian::ensureExists - ..create path")); |
|
699 // Set "created" flag only if successfull |
|
700 created = (status == KErrNone); |
|
701 } |
|
702 |
|
703 CX_DEBUG_EXIT_FUNCTION(); |
|
704 return status; |
|
705 } |
|
706 |
|
707 |
|
708 // end of file |