51 #include "cxestillcapturecontrolsymbianTraces.h" |
49 #include "cxestillcapturecontrolsymbianTraces.h" |
52 #endif |
50 #endif |
53 |
51 |
54 |
52 |
55 // constants |
53 // constants |
56 const int KMaintainAspectRatio = false; |
54 namespace |
57 const TInt64 KMinRequiredSpaceImage = 2000000; |
55 { |
58 |
56 const TInt64 KMinRequiredSpaceImage = 2000000; |
59 |
57 } |
60 /** |
58 |
|
59 /*! |
61 * Constructor. |
60 * Constructor. |
62 */ |
61 */ |
63 CxeStillCaptureControlSymbian::CxeStillCaptureControlSymbian( |
62 CxeStillCaptureControlSymbian::CxeStillCaptureControlSymbian( |
64 CxeCameraDevice &cameraDevice, |
63 CxeCameraDevice &cameraDevice, |
65 CxeViewfinderControl &viewfinderControl, |
64 CxeViewfinderControl &viewfinderControl, |
|
65 CxeSnapshotControl &snapshotControl, |
66 CxeCameraDeviceControl &cameraDeviceControl, |
66 CxeCameraDeviceControl &cameraDeviceControl, |
67 CxeFilenameGenerator &nameGenerator, |
67 CxeFilenameGenerator &nameGenerator, |
68 CxeSensorEventHandler &sensorEventHandler, |
68 CxeSensorEventHandler &sensorEventHandler, |
69 CxeAutoFocusControl &autoFocusControl, |
69 CxeAutoFocusControl &autoFocusControl, |
70 CxeSettings &settings, |
70 CxeSettings &settings, |
72 CxeFileSaveThread &fileSaveThread, |
72 CxeFileSaveThread &fileSaveThread, |
73 CxeDiskMonitor &diskMonitor) |
73 CxeDiskMonitor &diskMonitor) |
74 : CxeStateMachine("CxeStillCaptureControlSymbian"), |
74 : CxeStateMachine("CxeStillCaptureControlSymbian"), |
75 mCameraDevice(cameraDevice), |
75 mCameraDevice(cameraDevice), |
76 mViewfinderControl(viewfinderControl), |
76 mViewfinderControl(viewfinderControl), |
|
77 mSnapshotControl(snapshotControl), |
77 mCameraDeviceControl(cameraDeviceControl), |
78 mCameraDeviceControl(cameraDeviceControl), |
78 mFilenameGenerator(nameGenerator), |
79 mFilenameGenerator(nameGenerator), |
79 mSensorEventHandler(sensorEventHandler), |
80 mSensorEventHandler(sensorEventHandler), |
80 mAutoFocusControl(autoFocusControl), |
81 mAutoFocusControl(autoFocusControl), |
81 mSettings(settings), |
82 mSettings(settings), |
114 this, SLOT(handleSettingValueChanged(const QString&,QVariant))); |
115 this, SLOT(handleSettingValueChanged(const QString&,QVariant))); |
115 |
116 |
116 // Connect ECam image buffer ready event |
117 // Connect ECam image buffer ready event |
117 connect(&mCameraDeviceControl, SIGNAL(imageBufferReady(MCameraBuffer*,int)), |
118 connect(&mCameraDeviceControl, SIGNAL(imageBufferReady(MCameraBuffer*,int)), |
118 this, SLOT(handleImageData(MCameraBuffer*,int))); |
119 this, SLOT(handleImageData(MCameraBuffer*,int))); |
119 // Connect signals for ECam events |
120 // connect snapshot ready signal |
120 connect(&mCameraDeviceControl, SIGNAL(cameraEvent(int,int)), |
121 connect(&mSnapshotControl, SIGNAL(snapshotReady(CxeError::Id, const QImage&)), |
121 this, SLOT(handleCameraEvent(int,int))); |
122 this, SLOT(handleSnapshotReady(CxeError::Id, const QImage&))); |
122 |
123 |
123 OstTrace0(camerax_performance, CXESTILLCAPTURECONTROLSYMBIAN_CREATE_MID2, "msg: e_CX_ENGINE_CONNECT_SIGNALS 0"); |
124 OstTrace0(camerax_performance, CXESTILLCAPTURECONTROLSYMBIAN_CREATE_MID2, "msg: e_CX_ENGINE_CONNECT_SIGNALS 0"); |
124 |
125 |
125 mImageDataQueue = new CxeImageDataQueueSymbian(); |
126 mImageDataQueue = new CxeImageDataQueueSymbian(); |
126 mAutoFocusSoundPlayer = new CxeSoundPlayerSymbian(CxeSoundPlayerSymbian::AutoFocus); |
127 mAutoFocusSoundPlayer = new CxeSoundPlayerSymbian(CxeSoundPlayerSymbian::AutoFocus, mSettings); |
127 mCaptureSoundPlayer = new CxeSoundPlayerSymbian(CxeSoundPlayerSymbian::StillCapture); |
128 mCaptureSoundPlayer = new CxeSoundPlayerSymbian(CxeSoundPlayerSymbian::StillCapture, mSettings); |
128 |
129 |
129 OstTrace0(camerax_performance, CXESTILLCAPTURECONTROLSYMBIAN_CREATE_OUT, "msg: e_CX_STILLCAPTURECONTROL_NEW 0"); |
130 OstTrace0(camerax_performance, CXESTILLCAPTURECONTROLSYMBIAN_CREATE_OUT, "msg: e_CX_STILLCAPTURECONTROL_NEW 0"); |
130 CX_DEBUG_EXIT_FUNCTION(); |
131 CX_DEBUG_EXIT_FUNCTION(); |
131 } |
132 } |
132 |
133 |
133 /** |
134 /*! |
134 * Destructor. |
135 * Destructor. |
135 */ |
136 */ |
136 CxeStillCaptureControlSymbian::~CxeStillCaptureControlSymbian() |
137 CxeStillCaptureControlSymbian::~CxeStillCaptureControlSymbian() |
137 { |
138 { |
138 CX_DEBUG_ENTER_FUNCTION(); |
139 CX_DEBUG_ENTER_FUNCTION(); |
146 delete mAutoFocusSoundPlayer; |
147 delete mAutoFocusSoundPlayer; |
147 |
148 |
148 CX_DEBUG_EXIT_FUNCTION(); |
149 CX_DEBUG_EXIT_FUNCTION(); |
149 } |
150 } |
150 |
151 |
151 /** |
152 /*! |
152 * Return the current state. |
153 * Return the current state. |
153 */ |
154 */ |
154 CxeStillCaptureControl::State CxeStillCaptureControlSymbian::state() const |
155 CxeStillCaptureControl::State CxeStillCaptureControlSymbian::state() const |
155 { |
156 { |
156 return static_cast<CxeStillCaptureControl::State>( stateId() ); |
157 return static_cast<CxeStillCaptureControl::State>( stateId() ); |
157 } |
158 } |
158 |
159 |
159 /** |
160 /*! |
160 * Handle state changed event. Normally just emits the signal |
161 * Handle state changed event. Normally just emits the signal |
161 * for observers to react appropriately. |
162 * for observers to react appropriately. |
162 */ |
163 */ |
163 void CxeStillCaptureControlSymbian::handleStateChanged( int newStateId, CxeError::Id error ) |
164 void CxeStillCaptureControlSymbian::handleStateChanged( int newStateId, CxeError::Id error ) |
164 { |
165 { |
165 emit stateChanged( static_cast<State>( newStateId ), error ); |
166 emit stateChanged( static_cast<State>( newStateId ), error ); |
166 } |
167 } |
167 |
168 |
168 /** |
169 /*! |
169 * Initialize the control states. |
170 * Initialize the control states. |
170 */ |
171 */ |
171 void CxeStillCaptureControlSymbian::initializeStates() |
172 void CxeStillCaptureControlSymbian::initializeStates() |
172 { |
173 { |
173 // addState( id, name, allowed next states ) |
174 // addState( id, name, allowed next states ) |
206 if (state() == Uninitialized) { |
207 if (state() == Uninitialized) { |
207 // nothing to do |
208 // nothing to do |
208 return; |
209 return; |
209 } |
210 } |
210 |
211 |
211 OstTrace0( camerax_performance, CXESTILLCAPTURECONTROLSYMBIAN_DEINIT_IN, "msg: e_CX_STILL_CAPCONT_DEINIT 1" ); |
212 OstTrace0( camerax_performance, CXESTILLCAPTURECONTROLSYMBIAN_DEINIT_IN, "msg: e_CX_STILLCAPCONT_DEINIT 1" ); |
212 |
213 |
213 // Stop monitoring disk space. |
214 // Stop monitoring disk space. |
214 mDiskMonitor.stop(); |
215 mDiskMonitor.stop(); |
215 disconnect(&mDiskMonitor, SIGNAL(diskSpaceChanged()), this, SLOT(handleDiskSpaceChanged())); |
216 disconnect(&mDiskMonitor, SIGNAL(diskSpaceChanged()), this, SLOT(handleDiskSpaceChanged())); |
216 |
217 |
217 //stop viewfinder |
218 //stop viewfinder |
218 mViewfinderControl.stop(); |
219 mViewfinderControl.stop(); |
219 |
220 |
|
221 if (state() == Capturing) { |
|
222 mCameraDevice.camera()->CancelCaptureImage(); |
|
223 } |
|
224 |
220 // disable sensor event handler. |
225 // disable sensor event handler. |
221 mSensorEventHandler.deinit(); |
226 mSensorEventHandler.deinit(); |
222 |
227 |
223 if (mCameraDevice.cameraSnapshot()) { |
228 mSnapshotControl.stop(); |
224 mCameraDevice.cameraSnapshot()->StopSnapshot(); |
229 |
225 } |
|
226 |
|
227 if (state() == Capturing) { |
|
228 mCameraDevice.camera()->CancelCaptureImage(); |
|
229 } |
|
230 setState(Uninitialized); |
230 setState(Uninitialized); |
231 |
231 |
232 OstTrace0( camerax_performance, CXESTILLCAPTURECONTROLSYMBIAN_DEINIT_OUT, "msg: e_CX_STILL_CAPCONT_DEINIT 0" ); |
232 OstTrace0( camerax_performance, CXESTILLCAPTURECONTROLSYMBIAN_DEINIT_OUT, "msg: e_CX_STILLCAPCONT_DEINIT 0" ); |
233 CX_DEBUG_EXIT_FUNCTION(); |
233 CX_DEBUG_EXIT_FUNCTION(); |
234 } |
234 } |
235 |
235 |
236 |
236 |
237 /**! |
237 /*! |
238 * Prepare still capture mode. |
238 * Prepare still capture mode. |
239 */ |
239 */ |
240 void CxeStillCaptureControlSymbian::prepare() |
240 void CxeStillCaptureControlSymbian::prepare() |
241 { |
241 { |
242 CX_DEBUG_ENTER_FUNCTION(); |
242 CX_DEBUG_ENTER_FUNCTION(); |
269 ecamStillResolutionIndex = 0; |
269 ecamStillResolutionIndex = 0; |
270 } |
270 } |
271 |
271 |
272 // Prepare Image capture |
272 // Prepare Image capture |
273 CCamera::TFormat imgFormat = supportedStillFormat(mCameraDeviceControl.cameraIndex()); |
273 CCamera::TFormat imgFormat = supportedStillFormat(mCameraDeviceControl.cameraIndex()); |
274 OstTrace0(camerax_performance, CXESTILLCAPTURECONTROLSYMBIAN_PREPARE_MID1, "msg: e_CX_PREPARE_IMAGE_CAPTURE 1"); |
274 OstTrace0(camerax_performance, CXESTILLCAPTURECONTROL_PREPARE_MID1, "msg: e_CX_PREPARE_IMAGE_CAPTURE 1"); |
275 TRAP(err, mCameraDevice.camera()->PrepareImageCaptureL(imgFormat, ecamStillResolutionIndex)); |
275 TRAP(err, mCameraDevice.camera()->PrepareImageCaptureL(imgFormat, ecamStillResolutionIndex)); |
276 OstTrace0(camerax_performance, CXESTILLCAPTURECONTROLSYMBIAN_PREPARE_MID2, "msg: e_CX_PREPARE_IMAGE_CAPTURE 0"); |
276 OstTrace0(camerax_performance, CXESTILLCAPTURECONTROL_PREPARE_MID2, "msg: e_CX_PREPARE_IMAGE_CAPTURE 0"); |
277 |
277 |
278 CX_DEBUG(("PrepareImageCaptureL done, err=%d, resolution index = %d", err, ecamStillResolutionIndex)); |
278 CX_DEBUG(("PrepareImageCaptureL done, err=%d, resolution index = %d", err, ecamStillResolutionIndex)); |
279 |
279 |
280 if (!err) { |
280 if (!err) { |
281 // still capture prepare went fine, try preparing snapshot |
281 // still capture prepare went fine, try preparing snapshot |
316 } |
316 } |
317 |
317 |
318 // Inform interested parties that image mode has been prepared for capture |
318 // Inform interested parties that image mode has been prepared for capture |
319 emit imagePrepareComplete(CxeErrorHandlingSymbian::map(err)); |
319 emit imagePrepareComplete(CxeErrorHandlingSymbian::map(err)); |
320 |
320 |
321 OstTrace0( camerax_performance, CXESTILLCAPTURECONTROLSYMBIAN_PREPARE_OUT, "msg: e_CX_STILLCAPCONT_PREPARE 0" ); |
321 OstTrace0(camerax_performance, CXESTILLCAPTURECONTROL_GOTOSTILL, "msg: e_CX_GO_TO_STILL_MODE 0"); |
322 |
322 OstTrace0(camerax_performance, CXESTILLCAPTURECONTROL_PREPARE_OUT, "msg: e_CX_STILLCAPCONT_PREPARE 0"); |
323 CX_DEBUG_EXIT_FUNCTION(); |
323 |
324 } |
324 CX_DEBUG_EXIT_FUNCTION(); |
325 |
325 } |
326 |
326 |
327 |
327 |
328 /**! |
328 |
|
329 /*! |
329 Prepare still snapshot |
330 Prepare still snapshot |
330 Returns symbian error code. |
331 Returns symbian error code. |
331 */ |
332 */ |
332 int CxeStillCaptureControlSymbian::prepareStillSnapshot() |
333 int CxeStillCaptureControlSymbian::prepareStillSnapshot() |
333 { |
334 { |
334 CX_DEBUG_ENTER_FUNCTION(); |
335 CX_DEBUG_ENTER_FUNCTION(); |
335 |
336 OstTrace0( camerax_performance, CXESTILLCAPTURECONTROL_PREPARESNAP_1, "msg: e_CX_PREPARE_SNAPSHOT 1" ); |
336 CCamera::CCameraSnapshot *cameraSnapshot = mCameraDevice.cameraSnapshot(); |
337 |
337 CX_ASSERT_ALWAYS(cameraSnapshot); |
338 int status(KErrNone); |
338 |
339 try { |
339 int err = KErrNone; |
340 QSize snapshotSize = mSnapshotControl.calculateSnapshotSize( |
340 // Whether or not we have postcapture on, we need the snapshot for Thumbnail Manager. |
341 mViewfinderControl.deviceDisplayResolution(), |
341 if (cameraSnapshot) { |
342 mCurrentImageDetails.mAspectRatio); |
342 // Cancel active snapshot |
343 mSnapshotControl.start(snapshotSize); |
343 cameraSnapshot->StopSnapshot(); |
344 } catch (...) { |
344 |
345 status = KErrGeneral; |
345 // Prepare snapshot |
346 } |
346 CCamera::TFormat snapFormat = CCamera::EFormatFbsBitmapColor16MU; |
347 OstTrace0( camerax_performance, CXESTILLCAPTURECONTROL_PREPARESNAP_2, "msg: e_CX_PREPARE_SNAPSHOT 0" ); |
347 OstTrace0( camerax_performance, DUP4_CXESTILLCAPTURECONTROLSYMBIAN_PREPARE, "msg: e_CX_PREPARE_SNAPSHOT 1" ); |
348 |
348 TRAP(err, cameraSnapshot->PrepareSnapshotL(snapFormat, |
349 CX_DEBUG_EXIT_FUNCTION(); |
349 getSnapshotSize(), |
350 return status; |
350 KMaintainAspectRatio)); |
351 } |
351 OstTrace0( camerax_performance, DUP5_CXESTILLCAPTURECONTROLSYMBIAN_PREPARE, "msg: e_CX_PREPARE_SNAPSHOT 0" ); |
352 |
352 CX_DEBUG(("PrepareSnapshotL done, err=%d", err)); |
353 |
353 |
354 /*! |
354 // Start snapshot if no errors encountered. |
|
355 if (err == KErrNone) { |
|
356 CX_DEBUG(("Start still snapshot")); |
|
357 cameraSnapshot->StartSnapshot(); |
|
358 } |
|
359 } else { |
|
360 // No snapshot interface available. Report error. |
|
361 // Assert above takes care of this, but keeping this as an option. |
|
362 err = KErrNotReady; |
|
363 } |
|
364 |
|
365 CX_DEBUG_EXIT_FUNCTION(); |
|
366 |
|
367 return err; |
|
368 } |
|
369 |
|
370 |
|
371 /**! |
|
372 imageInfo contains image qualities details |
355 imageInfo contains image qualities details |
373 Returns CxeError error code. |
356 Returns CxeError error code. |
374 */ |
357 */ |
375 CxeError::Id CxeStillCaptureControlSymbian::getImageQualityDetails(CxeImageDetails &imageInfo) |
358 CxeError::Id CxeStillCaptureControlSymbian::getImageQualityDetails(CxeImageDetails &imageInfo) |
376 { |
359 { |
377 CX_DEBUG_ENTER_FUNCTION(); |
360 CX_DEBUG_ENTER_FUNCTION(); |
|
361 OstTrace0( camerax_performance, CXESTILLCAPTURECONTROL_GETQUALITYDETAILS_1, "msg: e_CX_GET_QUALITY_DETAILS 1" ); |
378 |
362 |
379 int imageQuality = 0; |
363 int imageQuality = 0; |
380 CxeError::Id err = CxeError::None; |
364 CxeError::Id err = CxeError::None; |
381 if (mCameraDeviceControl.cameraIndex() == Cxe::PrimaryCameraIndex) { |
365 if (mCameraDeviceControl.cameraIndex() == Cxe::PrimaryCameraIndex) { |
382 err = mSettings.get(CxeSettingIds::IMAGE_QUALITY, imageQuality); |
366 err = mSettings.get(CxeSettingIds::IMAGE_QUALITY, imageQuality); |
394 // we are in secondary camera |
378 // we are in secondary camera |
395 // get secondary camera image quality details |
379 // get secondary camera image quality details |
396 imageInfo = mIcmSupportedImageResolutions.at(imageQuality); |
380 imageInfo = mIcmSupportedImageResolutions.at(imageQuality); |
397 } |
381 } |
398 |
382 |
|
383 OstTrace0( camerax_performance, CXESTILLCAPTURECONTROL_GETQUALITYDETAILS_2, "msg: e_CX_GET_QUALITY_DETAILS 0" ); |
399 CX_DEBUG_EXIT_FUNCTION(); |
384 CX_DEBUG_EXIT_FUNCTION(); |
400 return err; |
385 return err; |
401 } |
386 } |
402 |
387 |
403 |
388 /*! |
404 /*! |
|
405 * Returns snapshot size. Snapshot size is calculated based on the |
|
406 * display resolution and current image aspect ratio. |
|
407 */ |
|
408 TSize CxeStillCaptureControlSymbian::getSnapshotSize() const |
|
409 { |
|
410 CX_DEBUG_ENTER_FUNCTION(); |
|
411 |
|
412 TSize snapshotSize; |
|
413 |
|
414 QSize deviceResolution = mViewfinderControl.deviceDisplayResolution(); |
|
415 QSize size = QSize(mCurrentImageDetails.mWidth, mCurrentImageDetails.mHeight); |
|
416 |
|
417 // scale according to aspect ratio. |
|
418 size.scale(deviceResolution.width(), deviceResolution.height(), Qt::KeepAspectRatio); |
|
419 CX_DEBUG(("Still Snapshot size, (%d,%d)", size.width(), size.height())); |
|
420 snapshotSize.SetSize(size.width(), deviceResolution.height()); |
|
421 |
|
422 CX_DEBUG_EXIT_FUNCTION(); |
|
423 |
|
424 return snapshotSize; |
|
425 } |
|
426 |
|
427 |
|
428 /** |
|
429 * Command to start image capture now. |
389 * Command to start image capture now. |
|
390 * @sa handleCameraEvent |
430 */ |
391 */ |
431 void CxeStillCaptureControlSymbian::capture() |
392 void CxeStillCaptureControlSymbian::capture() |
432 { |
393 { |
433 CX_DEBUG_ENTER_FUNCTION(); |
394 CX_DEBUG_ENTER_FUNCTION(); |
434 CX_ASSERT_ALWAYS(mCameraDevice.camera()); |
395 CX_ASSERT_ALWAYS(mCameraDevice.camera()); |
435 |
396 |
436 // Start the image capture as fast as possible to minimize lag. |
397 // Start the image capture as fast as possible to minimize lag. |
437 // Check e.g. space available *after* this. |
398 // Check e.g. space available *after* this. |
|
399 // Capture sound will be played when we receive "image capture event" from ECAM. |
438 mCameraDevice.camera()->CaptureImage(); |
400 mCameraDevice.camera()->CaptureImage(); |
439 |
401 |
440 if (imagesLeft() > 0) { |
402 if (imagesLeft() > 0) { |
441 mCaptureSoundPlayer->play(); |
|
442 setState(Capturing); |
403 setState(Capturing); |
443 |
404 |
444 //! @todo: NOTE: This call may not stay here. It can move depending on the implementation for burst capture. |
405 //! @todo: NOTE: This call may not stay here. It can move depending on the implementation for burst capture. |
445 if (mMode == BurstCapture) { |
406 if (mMode == BurstCapture) { |
446 // Start a new filename sequence |
407 // Start a new filename sequence |
479 CX_DEBUG_EXIT_FUNCTION(); |
440 CX_DEBUG_EXIT_FUNCTION(); |
480 |
441 |
481 return imgFormat; |
442 return imgFormat; |
482 } |
443 } |
483 |
444 |
484 |
445 /*! |
485 /** |
|
486 * Camera events. Only relevant one(s) are handled. |
|
487 */ |
|
488 void CxeStillCaptureControlSymbian::handleCameraEvent(int eventUid, int error) |
|
489 { |
|
490 CX_DEBUG_ENTER_FUNCTION(); |
|
491 |
|
492 if (eventUid == KUidECamEventSnapshotUidValue && |
|
493 mCameraDeviceControl.mode() == Cxe::ImageMode) { |
|
494 handleSnapshotEvent(CxeErrorHandlingSymbian::map(error)); |
|
495 } |
|
496 |
|
497 CX_DEBUG_EXIT_FUNCTION(); |
|
498 } |
|
499 |
|
500 /** |
|
501 * Snapshot ready notification. Ask the snapshot from snapshot interface. |
446 * Snapshot ready notification. Ask the snapshot from snapshot interface. |
502 * NB: Typically snapshot arrives before image data but can be in reverse |
447 * NB: Typically snapshot arrives before image data but can be in reverse |
503 * order as well. |
448 * order as well. |
504 */ |
449 * |
505 void CxeStillCaptureControlSymbian::handleSnapshotEvent(CxeError::Id error) |
450 * @param status Status of snapshot creation. CxeError::None if no error, otherwise contains the error code. |
506 { |
451 * @param snapshot Snapshot as QImage |
507 CX_DEBUG_ENTER_FUNCTION(); |
452 */ |
508 |
453 void CxeStillCaptureControlSymbian::handleSnapshotReady(CxeError::Id status, const QImage &snapshot) |
509 if (state() == CxeStillCaptureControl::Uninitialized) { |
454 { |
510 // we ignore this event, when we are not active |
455 CX_DEBUG_ENTER_FUNCTION(); |
511 return; |
456 if (mCameraDeviceControl.mode() == Cxe::ImageMode) { |
512 } |
457 |
513 |
458 OstTrace0(camerax_performance, CXESTILLCAPTURECONTROL_HANDLESNAPSHOT_1, "msg: e_CX_HANDLE_SNAPSHOT 1"); |
514 OstTrace0( camerax_performance, CXESTILLCAPTURECONTROLSYMBIAN_HANDLESNAPSHOTEVENT, "msg: e_CX_HANDLE_SNAPSHOT 1" ); |
459 |
515 |
460 QPixmap ss = QPixmap::fromImage(snapshot); |
516 // Get image container for current snapshot index. |
461 // Get image container for current snapshot index. |
517 // Remember to increment counter. |
462 // Remember to increment counter. |
518 CxeStillImageSymbian* stillImage = getImageForIndex(mNextSnapshotIndex++); |
463 CxeStillImageSymbian* stillImage = getImageForIndex(mNextSnapshotIndex++); |
519 |
464 if (status == CxeError::None) { |
520 if (error == CxeError::None) { |
465 stillImage->setSnapshot(ss); |
521 try { |
466 } |
522 stillImage->setSnapshot(extractSnapshot()); |
467 |
523 } catch (const std::exception& ex) { |
468 // Emit snapshotReady signal in all cases (error or not) |
524 error = CxeError::General; |
469 emit snapshotReady(status, snapshot, stillImage->id()); |
525 } |
470 |
526 } |
471 // When the snapshot ready event is handled, prepare new filename. |
527 |
472 if (stillImage->filename().isEmpty()) { |
528 // Emit snapshotReady signal in all cases (error or not) |
473 // Error ignored at this point, try again when image data arrives. |
529 emit snapshotReady(error, stillImage->snapshot(), stillImage->id()); |
474 prepareFilename(stillImage); |
530 |
475 } |
531 // When the snapshot ready event is handled, prepare new filename. |
476 |
532 if (stillImage->filename().isEmpty()) { |
477 OstTrace0(camerax_performance, CXESTILLCAPTURECONTROL_HANDLESNAPSHOT_2, "msg: e_CX_HANDLE_SNAPSHOT 0"); |
533 // Error ignored at this point, try again when image data arrives. |
478 } |
534 prepareFilename(stillImage); |
479 |
535 } |
480 CX_DEBUG_EXIT_FUNCTION(); |
536 |
481 } |
537 OstTrace0( camerax_performance, DUP1_CXESTILLCAPTURECONTROLSYMBIAN_HANDLESNAPSHOTEVENT, "msg: e_CX_HANDLE_SNAPSHOT 0" ); |
482 |
538 CX_DEBUG_EXIT_FUNCTION(); |
483 /*! |
539 } |
484 * Handle ECAM events. |
540 |
485 * Needed only for capture sound synchronization. |
541 /** |
486 * @param eventUid ECAM event id. |
542 * Gets QPixmap snapshot from ECAM buffer, if available. |
487 * @param error Error code. KErrNone if operation has been successful. |
543 * @param buffer ECAM buffer containing the snapshot data. Will be released when this |
488 */ |
544 * method returns, even on exception. |
489 void CxeStillCaptureControlSymbian::handleCameraEvent(int eventUid, int error) |
545 */ |
490 { |
546 QPixmap CxeStillCaptureControlSymbian::extractSnapshot() |
491 if (eventUid == KUidECamEventImageCaptureEventUidValue && error == KErrNone) { |
547 { |
492 CX_DEBUG(("CxeStillCaptureControlSymbian::handleCameraEvent - image capture event")); |
548 CX_DEBUG_ENTER_FUNCTION(); |
493 if (state() == CxeStillCaptureControl::Capturing) { |
549 QPixmap pixmap; |
494 mCaptureSoundPlayer->play(); |
550 |
495 } |
551 if (mCameraDevice.cameraSnapshot()) { |
496 } |
552 |
497 } |
553 QT_TRAP_THROWING({ |
498 |
554 RArray<TInt> frameIndex; |
499 |
555 CleanupClosePushL(frameIndex); |
500 /*! |
556 |
|
557 MCameraBuffer &buffer(mCameraDevice.cameraSnapshot()->SnapshotDataL(frameIndex)); |
|
558 |
|
559 // Make sure buffer is released on leave / exception |
|
560 CxeCameraBufferCleanup cleaner(&buffer); |
|
561 TInt firstImageIndex(frameIndex.Find(0)); |
|
562 CFbsBitmap &snapshot(buffer.BitmapL(firstImageIndex)); |
|
563 |
|
564 CleanupStack::PopAndDestroy(); // frameIndex |
|
565 |
|
566 TSize size = snapshot.SizeInPixels(); |
|
567 TInt sizeInWords = size.iHeight * CFbsBitmap::ScanLineLength(size.iWidth, EColor16MU) / sizeof(TUint32); |
|
568 CX_DEBUG(("size %d x %d, sizeInWords = %d", size.iWidth, size.iHeight, sizeInWords )); |
|
569 |
|
570 TUint32* pixelData = new (ELeave) TUint32[ sizeInWords ]; |
|
571 // Convert to QImage |
|
572 snapshot.LockHeap(); |
|
573 TUint32* dataPtr = snapshot.DataAddress(); |
|
574 memcpy(pixelData, dataPtr, sizeof(TUint32)*sizeInWords); |
|
575 snapshot.UnlockHeap(); |
|
576 |
|
577 CX_DEBUG(("Creating QImage")); |
|
578 QImage *snapImage = new QImage((uchar*)pixelData, size.iWidth, size.iHeight, |
|
579 CFbsBitmap::ScanLineLength(size.iWidth, EColor16MU), |
|
580 QImage::Format_RGB32); |
|
581 |
|
582 pixmap = QPixmap::fromImage(*snapImage); |
|
583 delete [] pixelData; |
|
584 delete snapImage; |
|
585 }); |
|
586 } |
|
587 |
|
588 CX_DEBUG_EXIT_FUNCTION(); |
|
589 return pixmap; |
|
590 } |
|
591 |
|
592 /** |
|
593 * handleImageData: Image data received from ECam |
501 * handleImageData: Image data received from ECam |
594 */ |
502 */ |
595 void CxeStillCaptureControlSymbian::handleImageData(MCameraBuffer* cameraBuffer, int error) |
503 void CxeStillCaptureControlSymbian::handleImageData(MCameraBuffer* cameraBuffer, int error) |
596 { |
504 { |
597 CX_DEBUG_ENTER_FUNCTION(); |
505 CX_DEBUG_ENTER_FUNCTION(); |
636 if (!symbErr) { |
544 if (!symbErr) { |
637 //! @todo: this does a deep copy... we want to avoid this for performance/memory consumption reasons |
545 //! @todo: this does a deep copy... we want to avoid this for performance/memory consumption reasons |
638 QByteArray byteArray( reinterpret_cast<const char*>( data->Ptr() ), data->Size() ); |
546 QByteArray byteArray( reinterpret_cast<const char*>( data->Ptr() ), data->Size() ); |
639 data = NULL; |
547 data = NULL; |
640 |
548 |
|
549 // get geotagging setting value and check if we have to add location trail to image data. |
|
550 int value = Cxe::GeoTaggingOff; |
|
551 mSettings.get(CxeSettingIds::GEOTAGGING, value); |
|
552 |
641 // Save the image data |
553 // Save the image data |
642 CxeImageDataItemSymbian* dataItem = mImageDataQueue->startSave(byteArray, stillImage->filename(), stillImage->id()); |
554 CxeImageDataItemSymbian* dataItem = mImageDataQueue->startSave(byteArray, |
|
555 stillImage->filename(), |
|
556 stillImage->id(), |
|
557 value == Cxe::GeoTaggingOn); |
643 stillImage->setDataItem(dataItem); |
558 stillImage->setDataItem(dataItem); |
644 mFileSaveThread.save(dataItem); // Saving thread takes ownership of dataItem. |
559 mFileSaveThread.save(dataItem); // Saving thread takes ownership of dataItem. |
645 } |
560 } |
646 |
561 |
647 // ECam Camera buffer should always be released |
562 // ECam Camera buffer should always be released |
703 } |
618 } |
704 |
619 |
705 CX_DEBUG_EXIT_FUNCTION(); |
620 CX_DEBUG_EXIT_FUNCTION(); |
706 } |
621 } |
707 |
622 |
708 /** |
623 /*! |
709 * ECam reference changing, release resources |
624 * ECam reference changing, release resources |
710 */ |
625 */ |
711 void CxeStillCaptureControlSymbian::prepareForCameraDelete() |
626 void CxeStillCaptureControlSymbian::prepareForCameraDelete() |
712 { |
627 { |
713 CX_DEBUG_ENTER_FUNCTION(); |
628 CX_DEBUG_ENTER_FUNCTION(); |
714 deinit(); |
629 deinit(); |
715 CX_DEBUG_EXIT_FUNCTION(); |
630 CX_DEBUG_EXIT_FUNCTION(); |
716 } |
631 } |
717 |
632 |
718 /** |
633 /*! |
719 * Camera being released. Cancel ongoing capture, if any. |
634 * Camera being released. Cancel ongoing capture, if any. |
720 */ |
635 */ |
721 void CxeStillCaptureControlSymbian::prepareForRelease() |
636 void CxeStillCaptureControlSymbian::prepareForRelease() |
722 { |
637 { |
723 CX_DEBUG_ENTER_FUNCTION(); |
638 CX_DEBUG_ENTER_FUNCTION(); |
724 deinit(); |
639 deinit(); |
725 CX_DEBUG_EXIT_FUNCTION(); |
640 CX_DEBUG_EXIT_FUNCTION(); |
726 } |
641 } |
727 |
642 |
728 /** |
643 /*! |
729 * New camera available, |
644 * New camera available, |
730 */ |
645 */ |
731 void CxeStillCaptureControlSymbian::handleCameraAllocated(CxeError::Id error) |
646 void CxeStillCaptureControlSymbian::handleCameraAllocated(CxeError::Id error) |
732 { |
647 { |
733 CX_DEBUG_ENTER_FUNCTION(); |
648 CX_DEBUG_ENTER_FUNCTION(); |
781 mNextImageDataIndex = 0; |
696 mNextImageDataIndex = 0; |
782 |
697 |
783 CX_DEBUG_EXIT_FUNCTION(); |
698 CX_DEBUG_EXIT_FUNCTION(); |
784 } |
699 } |
785 |
700 |
786 /** |
701 /*! |
787 * This should cancel any ongoing image captures. |
702 * This should cancel any ongoing image captures. |
788 */ |
703 */ |
789 void CxeStillCaptureControlSymbian::cancelAll() |
704 void CxeStillCaptureControlSymbian::cancelAll() |
790 { |
705 { |
791 mImageDataQueue->clear(); |
706 mImageDataQueue->clear(); |
792 reset(); |
707 reset(); |
793 } |
708 } |
794 |
709 |
795 /** |
710 /*! |
796 * Sets the current capture mode: SingleImageCapture / BurstCapture. |
711 * Sets the current capture mode: SingleImageCapture / BurstCapture. |
797 */ |
712 */ |
798 void CxeStillCaptureControlSymbian::setMode( CaptureMode mode ) |
713 void CxeStillCaptureControlSymbian::setMode( CaptureMode mode ) |
799 { |
714 { |
800 mMode = mode; |
715 mMode = mode; |
801 } |
716 } |
802 |
717 |
803 /** |
718 /*! |
804 * Returns the current capture mode. |
719 * Returns the current capture mode. |
805 */ |
720 */ |
806 CxeStillCaptureControl::CaptureMode CxeStillCaptureControlSymbian::mode() const |
721 CxeStillCaptureControl::CaptureMode CxeStillCaptureControlSymbian::mode() const |
807 { |
722 { |
808 return mMode; |
723 return mMode; |
809 } |
724 } |
810 |
725 |
811 /** |
726 /*! |
812 * Operator [] - returns the indexed image from capture array. |
727 * Operator [] - returns the indexed image from capture array. |
813 */ |
728 */ |
814 CxeStillImage &CxeStillCaptureControlSymbian::operator[]( int index ) |
729 CxeStillImage &CxeStillCaptureControlSymbian::operator[]( int index ) |
815 { |
730 { |
816 return *mImages[ index ]; |
731 return *mImages[ index ]; |
817 } |
732 } |
818 |
733 |
819 /** |
734 /*! |
820 * Getter for image data queue. |
735 * Getter for image data queue. |
821 */ |
736 */ |
822 CxeImageDataQueue &CxeStillCaptureControlSymbian::imageDataQueue() |
737 CxeImageDataQueue &CxeStillCaptureControlSymbian::imageDataQueue() |
823 { |
738 { |
824 return *mImageDataQueue; |
739 return *mImageDataQueue; |
825 } |
740 } |
826 |
741 |
827 /** |
742 /*! |
828 * Generates a filename and sets it in the still image object. |
743 * Generates a filename and sets it in the still image object. |
829 * Skips the process if filename already copied exists in the object. This |
744 * Skips the process if filename already copied exists in the object. This |
830 * behaviour is required in rare cases where image data arrives before snapshot. |
745 * behaviour is required in rare cases where image data arrives before snapshot. |
831 */ |
746 */ |
832 CxeError::Id |
747 CxeError::Id |
833 CxeStillCaptureControlSymbian::prepareFilename(CxeStillImageSymbian *stillImage) |
748 CxeStillCaptureControlSymbian::prepareFilename(CxeStillImageSymbian *stillImage) |
834 { |
749 { |
|
750 OstTrace0(camerax_performance, CXESTILLCAPTURECONTROLSYMBIAN_PREPAREFILENAME_1, "msg: e_CX_PREPARE_FILENAME 1" ); |
|
751 |
835 CxeError::Id err = CxeError::None; |
752 CxeError::Id err = CxeError::None; |
836 if (stillImage->filename().isEmpty()) { |
753 if (stillImage->filename().isEmpty()) { |
837 QString path; |
754 QString path; |
838 |
755 |
839 QString fileExt = mCurrentImageDetails.mImageFileExtension; |
756 QString fileExt = mCurrentImageDetails.mImageFileExtension; |