camerauis/cameraxui/cxengine/src/cxestillcapturecontrolsymbian.cpp
branchRCL_3
changeset 54 bac7acad7cb3
parent 53 61bc0f252b2b
child 57 2c87b2808fd7
equal deleted inserted replaced
53:61bc0f252b2b 54:bac7acad7cb3
     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 
       
    18 
       
    19 #include <algorithm>
       
    20 #include <exception>
       
    21 #include <QPixmap>
       
    22 #include <coemain.h>
       
    23 #include <ECamOrientationCustomInterface2.h>
       
    24 #include <ecamfacetrackingcustomapi.h>
       
    25 #include <ecamusecasehintcustomapi.h>
       
    26 
       
    27 #include "cxestillcapturecontrolsymbian.h"
       
    28 #include "cxeimagedataqueuesymbian.h"
       
    29 #include "cxefilenamegenerator.h"
       
    30 #include "cxefilesavethread.h"
       
    31 #include "cxutils.h"
       
    32 #include "cxecameradevicecontrol.h"
       
    33 #include "cxecameradevice.h"
       
    34 #include "cxesoundplayersymbian.h"
       
    35 #include "cxestillimagesymbian.h"
       
    36 #include "cxeviewfindercontrolsymbian.h"
       
    37 #include "cxesnapshotcontrol.h"
       
    38 #include "cxesettingsmappersymbian.h"
       
    39 #include "cxestate.h"
       
    40 #include "cxesettings.h"
       
    41 #include "cxeerrormappingsymbian.h"
       
    42 #include "cxeautofocuscontrol.h"
       
    43 #include "cxesensoreventhandler.h"
       
    44 #include "cxesensoreventhandler.h"
       
    45 #include "cxequalitypresetssymbian.h"
       
    46 #include "cxediskmonitor.h"
       
    47 #include "cxeexception.h"
       
    48 
       
    49 #include "OstTraceDefinitions.h"
       
    50 #ifdef OST_TRACE_COMPILER_IN_USE
       
    51 #include "cxestillcapturecontrolsymbianTraces.h"
       
    52 #endif
       
    53 
       
    54 
       
    55 // constants
       
    56 namespace
       
    57 {
       
    58     const TInt64 KMinRequiredSpaceImage = 2000000;
       
    59 }
       
    60 
       
    61 /*!
       
    62  * Constructor.
       
    63  */
       
    64 CxeStillCaptureControlSymbian::CxeStillCaptureControlSymbian(
       
    65     CxeCameraDevice &cameraDevice,
       
    66     CxeViewfinderControl &viewfinderControl,
       
    67     CxeSnapshotControl &snapshotControl,
       
    68     CxeCameraDeviceControl &cameraDeviceControl,
       
    69     CxeFilenameGenerator &nameGenerator,
       
    70     CxeSensorEventHandler &sensorEventHandler,
       
    71     CxeAutoFocusControl &autoFocusControl,
       
    72     CxeSettings &settings,
       
    73     CxeQualityPresets &qualityPresets,
       
    74     CxeFileSaveThread &fileSaveThread,
       
    75     CxeDiskMonitor &diskMonitor)
       
    76     : CxeStateMachine("CxeStillCaptureControlSymbian"),
       
    77       mCameraDevice(cameraDevice),
       
    78       mViewfinderControl(viewfinderControl),
       
    79       mSnapshotControl(snapshotControl),
       
    80       mCameraDeviceControl(cameraDeviceControl),
       
    81       mFilenameGenerator(nameGenerator),
       
    82       mSensorEventHandler(sensorEventHandler),
       
    83       mAutoFocusControl(autoFocusControl),
       
    84       mSettings(settings),
       
    85       mQualityPresets(qualityPresets),
       
    86       mFileSaveThread(fileSaveThread),
       
    87       mDiskMonitor(diskMonitor),
       
    88       mMode(SingleImageCapture),
       
    89       mAfState(CxeAutoFocusControl::Unknown)
       
    90 {
       
    91     CX_DEBUG_ENTER_FUNCTION();
       
    92     OstTrace0(camerax_performance, CXESTILLCAPTURECONTROLSYMBIAN_CREATE_IN, "msg: e_CX_STILLCAPTURECONTROL_NEW 1");
       
    93 
       
    94     qRegisterMetaType<CxeStillCaptureControl::State>();
       
    95     initializeStates();
       
    96     reset();
       
    97 
       
    98     // If camera is already allocated, call the slot ourselves.
       
    99     if (mCameraDevice.camera()) {
       
   100         handleCameraAllocated(CxeError::None);
       
   101     }
       
   102 
       
   103     OstTrace0(camerax_performance, CXESTILLCAPTURECONTROLSYMBIAN_CREATE_MID1, "msg: e_CX_ENGINE_CONNECT_SIGNALS 1");
       
   104     // connect signals from cameraDevice to recieve events when camera reference changes
       
   105     connect(&cameraDevice, SIGNAL(prepareForCameraDelete()),
       
   106             this, SLOT(prepareForCameraDelete()));
       
   107     connect(&cameraDevice, SIGNAL(prepareForRelease()),
       
   108             this, SLOT(prepareForRelease()));
       
   109     connect(&cameraDevice, SIGNAL(cameraAllocated(CxeError::Id)),
       
   110             this, SLOT(handleCameraAllocated(CxeError::Id)));
       
   111     connect(&mSensorEventHandler,
       
   112             SIGNAL(sensorEvent(CxeSensorEventHandler::SensorType,QVariant)),
       
   113             this, SLOT(handleSensorEvent(CxeSensorEventHandler::SensorType,QVariant)));
       
   114 
       
   115     // enabling setting change callbacks to stillcapturecontrol
       
   116     connect(&mSettings, SIGNAL(settingValueChanged(const QString&,QVariant)),
       
   117             this, SLOT(handleSettingValueChanged(const QString&,QVariant)));
       
   118 
       
   119     // Connect ECam image buffer ready event
       
   120     connect(&mCameraDeviceControl, SIGNAL(imageBufferReady(MCameraBuffer*,int)),
       
   121             this, SLOT(handleImageData(MCameraBuffer*,int)));
       
   122     // connect snapshot ready signal
       
   123     connect(&mSnapshotControl, SIGNAL(snapshotReady(CxeError::Id, const QImage&)),
       
   124             this, SLOT(handleSnapshotReady(CxeError::Id, const QImage&)));
       
   125 
       
   126     OstTrace0(camerax_performance, CXESTILLCAPTURECONTROLSYMBIAN_CREATE_MID2, "msg: e_CX_ENGINE_CONNECT_SIGNALS 0");
       
   127 
       
   128     mImageDataQueue = new CxeImageDataQueueSymbian();
       
   129     mAutoFocusSoundPlayer = new CxeSoundPlayerSymbian(CxeSoundPlayerSymbian::AutoFocus, mSettings);
       
   130     mCaptureSoundPlayer = new CxeSoundPlayerSymbian(CxeSoundPlayerSymbian::StillCapture, mSettings);
       
   131 
       
   132     OstTrace0(camerax_performance, CXESTILLCAPTURECONTROLSYMBIAN_CREATE_OUT, "msg: e_CX_STILLCAPTURECONTROL_NEW 0");
       
   133     CX_DEBUG_EXIT_FUNCTION();
       
   134 }
       
   135 
       
   136 /*!
       
   137  * Destructor.
       
   138  */
       
   139 CxeStillCaptureControlSymbian::~CxeStillCaptureControlSymbian()
       
   140 {
       
   141     CX_DEBUG_ENTER_FUNCTION();
       
   142 
       
   143     deinit();
       
   144     reset();
       
   145     mIcmSupportedImageResolutions.clear();
       
   146     mECamSupportedImageResolutions.clear();
       
   147     delete mImageDataQueue;
       
   148     delete mCaptureSoundPlayer;
       
   149     delete mAutoFocusSoundPlayer;
       
   150 
       
   151     CX_DEBUG_EXIT_FUNCTION();
       
   152 }
       
   153 
       
   154 /*!
       
   155  * Return the current state.
       
   156  */
       
   157 CxeStillCaptureControl::State CxeStillCaptureControlSymbian::state() const
       
   158 {
       
   159     return static_cast<CxeStillCaptureControl::State>( stateId() );
       
   160 }
       
   161 
       
   162 /*!
       
   163  * Handle state changed event. Normally just emits the signal
       
   164  * for observers to react appropriately.
       
   165  */
       
   166 void CxeStillCaptureControlSymbian::handleStateChanged( int newStateId, CxeError::Id error )
       
   167 {
       
   168     emit stateChanged( static_cast<State>( newStateId ), error );
       
   169 }
       
   170 
       
   171 /*!
       
   172  * Initialize the control states.
       
   173  */
       
   174 void CxeStillCaptureControlSymbian::initializeStates()
       
   175 {
       
   176     // addState( id, name, allowed next states )
       
   177     addState(new CxeState( Uninitialized , "Uninitialized", Ready));
       
   178     addState(new CxeState( Ready , "Ready", Uninitialized | Capturing));
       
   179     addState(new CxeState( Capturing , "Capturing", Uninitialized | Ready));
       
   180 
       
   181     setInitialState(Uninitialized);
       
   182 }
       
   183 
       
   184 /*!
       
   185  * Initialize the still image capture control.
       
   186  */
       
   187 void CxeStillCaptureControlSymbian::init()
       
   188 {
       
   189     CX_DEBUG_ENTER_FUNCTION();
       
   190     OstTrace0(camerax_performance, CXESTILLCAPTURECONTROLSYMBIAN_INIT_IN, "msg: e_CX_STILL_CAPCONT_INIT 1");
       
   191 
       
   192     if (state() == Uninitialized) {
       
   193         prepare();
       
   194         // Initialize orientation sensor and other sensors
       
   195         mSensorEventHandler.init();
       
   196     }
       
   197 
       
   198     OstTrace0(camerax_performance, CXESTILLCAPTURECONTROLSYMBIAN_INIT_OUT, "msg: e_CX_STILL_CAPCONT_INIT 0");
       
   199     CX_DEBUG_EXIT_FUNCTION();
       
   200 }
       
   201 
       
   202 /*!
       
   203  * Un-initialize the image mode.
       
   204  */
       
   205 void CxeStillCaptureControlSymbian::deinit()
       
   206 {
       
   207     CX_DEBUG_ENTER_FUNCTION();
       
   208 
       
   209     if (state() == Uninitialized) {
       
   210         // nothing to do
       
   211         return;
       
   212     }
       
   213 
       
   214     OstTrace0( camerax_performance, CXESTILLCAPTURECONTROLSYMBIAN_DEINIT_IN, "msg: e_CX_STILLCAPCONT_DEINIT 1" );
       
   215 
       
   216     // Stop monitoring disk space.
       
   217     mDiskMonitor.stop();
       
   218     disconnect(&mDiskMonitor, SIGNAL(diskSpaceChanged()), this, SLOT(handleDiskSpaceChanged()));
       
   219 
       
   220     //stop viewfinder
       
   221     mViewfinderControl.stop();
       
   222 
       
   223     if (state() == Capturing) {
       
   224         mCameraDevice.camera()->CancelCaptureImage();
       
   225     }
       
   226 
       
   227     // disable sensor event handler.
       
   228     mSensorEventHandler.deinit();
       
   229 
       
   230     mSnapshotControl.stop();
       
   231 
       
   232     setState(Uninitialized);
       
   233 
       
   234     OstTrace0( camerax_performance, CXESTILLCAPTURECONTROLSYMBIAN_DEINIT_OUT, "msg: e_CX_STILLCAPCONT_DEINIT 0" );
       
   235     CX_DEBUG_EXIT_FUNCTION();
       
   236 }
       
   237 
       
   238 
       
   239 /*!
       
   240  * Prepare still capture mode.
       
   241  */
       
   242 void CxeStillCaptureControlSymbian::prepare()
       
   243 {
       
   244     CX_DEBUG_ENTER_FUNCTION();
       
   245 
       
   246     if (state() != Uninitialized) {
       
   247         // wrong state and we return
       
   248         return;
       
   249     }
       
   250 
       
   251     OstTrace0(camerax_performance, CXESTILLCAPTURECONTROL_PREPARE_IN, "msg: e_CX_STILLCAPCONT_PREPARE 1");
       
   252 
       
   253     CxeError::Id status(CxeError::None);
       
   254 
       
   255     try {
       
   256         // Update capture parameters
       
   257         updateStillCaptureParameters();
       
   258 
       
   259         // Prepare Image capture
       
   260         CX_DEBUG(("Calling PrepareImageCaptureL, resolution index = %d", mSizeIndex));
       
   261         OstTrace0(camerax_performance, CXESTILLCAPTURECONTROL_PREPARE_MID1, "msg: e_CX_PREPARE_IMAGE_CAPTURE 1");
       
   262         QT_TRAP_THROWING(mCameraDevice.camera()->PrepareImageCaptureL(mCaptureFormat, mSizeIndex));
       
   263         OstTrace0(camerax_performance, CXESTILLCAPTURECONTROL_PREPARE_MID2, "msg: e_CX_PREPARE_IMAGE_CAPTURE 0");
       
   264 
       
   265         // Start viewfinder before claiming to be ready,
       
   266         // as e.g. pending capture might be started by state change,
       
   267         // and viewfinder start might have problems with just started capturing.
       
   268         // If viewfinder is already running, this call does nothing.
       
   269         mViewfinderControl.start();
       
   270 
       
   271         // Prepare snapshot
       
   272         prepareSnapshot();
       
   273 
       
   274         // Start monitoring disk space.
       
   275         mDiskMonitor.start();
       
   276         connect(&mDiskMonitor, SIGNAL(diskSpaceChanged()), this, SLOT(handleDiskSpaceChanged()));
       
   277 
       
   278         // Enable AF reticule drawing by adaptation
       
   279         MCameraFaceTracking *faceTracking = mCameraDevice.faceTracking();
       
   280         if (faceTracking) {
       
   281             TRAP_IGNORE(faceTracking->EnableFaceIndicatorsL(ETrue));
       
   282         }
       
   283 
       
   284         // Still capture and still snapshot are OK.
       
   285         // We can safely set state to READY.
       
   286         setState(Ready);
       
   287 
       
   288         // inform zoom control to prepare zoom
       
   289         emit prepareZoomForStill(mSizeIndex);
       
   290 
       
   291     } catch (const std::exception &e) {
       
   292         // Exception encountered, free resources.
       
   293         CX_DEBUG(("Image Prepare FAILED! symbian error = %d", qt_symbian_exception2Error(e)));
       
   294         status = CxeErrorHandlingSymbian::map(qt_symbian_exception2Error(e));
       
   295         deinit();
       
   296     }
       
   297 
       
   298     // Inform interested parties that image mode has been prepared for capture
       
   299     emit imagePrepareComplete(status);
       
   300 
       
   301     OstTrace0(camerax_performance, CXESTILLCAPTURECONTROL_GOTOSTILL, "msg: e_CX_GO_TO_STILL_MODE 0");
       
   302     OstTrace0(camerax_performance, CXESTILLCAPTURECONTROL_PREPARE_OUT, "msg: e_CX_STILLCAPCONT_PREPARE 0");
       
   303     CX_DEBUG_EXIT_FUNCTION();
       
   304 }
       
   305 
       
   306 
       
   307 
       
   308 /*!
       
   309  Prepare still snapshot
       
   310  Throws exception on error.
       
   311  */
       
   312 void CxeStillCaptureControlSymbian::prepareSnapshot()
       
   313 {
       
   314     CX_DEBUG_ENTER_FUNCTION();
       
   315     OstTrace0( camerax_performance, CXESTILLCAPTURECONTROL_PREPARESNAP_1, "msg: e_CX_PREPARE_SNAPSHOT 1" );
       
   316 
       
   317     QSize snapshotSize = mSnapshotControl.calculateSnapshotSize(
       
   318                             mViewfinderControl.deviceDisplayResolution(),
       
   319                             mCurrentImageDetails.mAspectRatio);
       
   320     mSnapshotControl.start(snapshotSize);
       
   321 
       
   322     OstTrace0( camerax_performance, CXESTILLCAPTURECONTROL_PREPARESNAP_2, "msg: e_CX_PREPARE_SNAPSHOT 0" );
       
   323     CX_DEBUG_EXIT_FUNCTION();
       
   324 }
       
   325 
       
   326 
       
   327 /*!
       
   328     Update image capture parameters. mCurrentImageDetails, mCaptureFormat and
       
   329     mSizeIndex are updated based on the current settings.
       
   330 */
       
   331 void CxeStillCaptureControlSymbian::updateStillCaptureParameters()
       
   332 {
       
   333     CX_DEBUG_ENTER_FUNCTION();
       
   334     OstTrace0( camerax_performance, CXESTILLCAPTURECONTROL_UPDATESTILLCAPTUREPARAMETERS_1, "msg: e_CX_UPDATE_STILL_CAPTURE_PARAMETERS 1" );
       
   335 
       
   336     int imageQuality = 0;
       
   337     CxeError::Id err = CxeError::None;
       
   338     if (mCameraDeviceControl.cameraIndex() == Cxe::PrimaryCameraIndex) {
       
   339         try {
       
   340             imageQuality = mSettings.get<int>(CxeSettingIds::IMAGE_QUALITY);
       
   341 
       
   342             bool validQuality = (imageQuality >= 0 &&
       
   343                                  imageQuality < mIcmSupportedImageResolutions.count());
       
   344 
       
   345             if (validQuality ) {
       
   346                 // get image quality details
       
   347                 mCurrentImageDetails = mIcmSupportedImageResolutions.at(imageQuality);
       
   348             } else {
       
   349                 err = CxeError::NotFound;
       
   350                 CX_DEBUG(("Invalid ImageQuality = %d", imageQuality));
       
   351             }
       
   352         } catch (CxeException &e) {
       
   353             err = (CxeError::Id) e.error();
       
   354         }
       
   355     } else {
       
   356         // we are in secondary camera
       
   357         // get secondary camera image quality details
       
   358        mCurrentImageDetails = mIcmSupportedImageResolutions.at(imageQuality);
       
   359     }
       
   360 
       
   361     mSizeIndex = 0;
       
   362 
       
   363     if (err == CxeError::None) {
       
   364         int imageWidth = mCurrentImageDetails.mWidth;
       
   365         int imageHeight = mCurrentImageDetails.mHeight;
       
   366         CX_DEBUG(("CxeStillCaptureControlSymbian::updateStillCaptureParameters <> resolution = (%d, %d)", imageWidth, imageHeight));
       
   367 
       
   368         TSize imageSize;
       
   369         imageSize.SetSize(imageWidth, imageHeight);
       
   370 
       
   371         if (mECamSupportedImageResolutions.count() > 0) {
       
   372             mSizeIndex = mECamSupportedImageResolutions.indexOf(imageSize);
       
   373         }
       
   374 
       
   375         if (mSizeIndex < 0) {
       
   376             CX_DEBUG(("CxeStillCaptureControlSymbian::updateStillCaptureParameters - WARNING! resolution not supported, falling back to index 0"));
       
   377             mSizeIndex = 0;
       
   378         }
       
   379 
       
   380         mCaptureFormat = supportedStillFormat(mCameraDeviceControl.cameraIndex());
       
   381     }
       
   382 
       
   383     OstTrace0( camerax_performance, CXESTILLCAPTURECONTROL_UPDATESTILLCAPTUREPARAMETERS_2, "msg: e_CX_UPDATE_STILL_CAPTURE_PARAMETERS 0" );
       
   384     CX_DEBUG_EXIT_FUNCTION();
       
   385 }
       
   386 
       
   387 /*!
       
   388  * Command to start image capture now.
       
   389  * @sa handleCameraEvent
       
   390  */
       
   391 void CxeStillCaptureControlSymbian::capture()
       
   392 {
       
   393     CX_DEBUG_ENTER_FUNCTION();
       
   394     CX_ASSERT_ALWAYS(mCameraDevice.camera());
       
   395 
       
   396     // Start the image capture as fast as possible to minimize lag.
       
   397     // Check e.g. space available *after* this.
       
   398     // Capture sound will be played when we receive "image capture event" from ECAM.
       
   399     mCameraDevice.camera()->CaptureImage();
       
   400 
       
   401     if (imagesLeft() > 0) {
       
   402         setState(Capturing);
       
   403 
       
   404         //! @todo: NOTE: This call may not stay here. It can move depending on the implementation for burst capture.
       
   405         if (mMode == BurstCapture) {
       
   406             // Start a new filename sequence
       
   407             mFilenameGenerator.startNewImageFilenameSequence();
       
   408         }
       
   409     } else {
       
   410         // There's no space for the image.
       
   411         // Cancel started capturing.
       
   412         mCameraDevice.camera()->CancelCaptureImage();
       
   413 
       
   414         // Report error.
       
   415         // Ui notification has anyway some delays, hence handling VF after this.
       
   416         emit imageCaptured(CxeError::DiskFull, CxeStillImage::INVALID_ID);
       
   417 
       
   418         // Capturing stops viewfinder, so restart it now.
       
   419         mViewfinderControl.stop();
       
   420         mViewfinderControl.start();
       
   421     }
       
   422 
       
   423     CX_DEBUG_EXIT_FUNCTION();
       
   424 }
       
   425 
       
   426 
       
   427 /*!
       
   428 @Param cameraIndex indicates which camera we are in use, primary/secondary
       
   429 Returns the format we use for specific camera index.
       
   430 */
       
   431 CCamera::TFormat CxeStillCaptureControlSymbian::supportedStillFormat(Cxe::CameraIndex cameraIndex)
       
   432 {
       
   433     CX_DEBUG_ENTER_FUNCTION();
       
   434     Q_UNUSED(cameraIndex);
       
   435 
       
   436     // The same image format used for both primary and secodary cameras
       
   437     CCamera::TFormat imgFormat = CCamera::EFormatExif;
       
   438 
       
   439     CX_DEBUG_EXIT_FUNCTION();
       
   440 
       
   441     return imgFormat;
       
   442 }
       
   443 
       
   444 /*!
       
   445  * Snapshot ready notification. Ask the snapshot from snapshot interface.
       
   446  * NB: Typically snapshot arrives before image data but can be in reverse
       
   447  * order as well.
       
   448  *
       
   449  * @param status Status of snapshot creation. CxeError::None if no error, otherwise contains the error code.
       
   450  * @param snapshot Snapshot as QImage
       
   451  */
       
   452 void CxeStillCaptureControlSymbian::handleSnapshotReady(CxeError::Id status, const QImage &snapshot)
       
   453 {
       
   454     CX_DEBUG_ENTER_FUNCTION();
       
   455     if (mCameraDeviceControl.mode() == Cxe::ImageMode) {
       
   456 
       
   457         OstTrace0(camerax_performance, CXESTILLCAPTURECONTROL_HANDLESNAPSHOT_1, "msg: e_CX_HANDLE_SNAPSHOT 1");
       
   458 
       
   459         QPixmap ss = QPixmap::fromImage(snapshot);
       
   460         // Get image container for current snapshot index.
       
   461         // Remember to increment counter.
       
   462         CxeStillImageSymbian* stillImage = getImageForIndex(mNextSnapshotIndex++);
       
   463         if (status == CxeError::None) {
       
   464             stillImage->setSnapshot(ss);
       
   465         }
       
   466 
       
   467         // Emit snapshotReady signal in all cases (error or not)
       
   468         emit snapshotReady(status, snapshot, stillImage->id());
       
   469 
       
   470         // When the snapshot ready event is handled, prepare new filename.
       
   471         if (stillImage->filename().isEmpty()) {
       
   472             // Error ignored at this point, try again when image data arrives.
       
   473             prepareFilename(stillImage);
       
   474         }
       
   475 
       
   476         OstTrace0(camerax_performance, CXESTILLCAPTURECONTROL_HANDLESNAPSHOT_2, "msg: e_CX_HANDLE_SNAPSHOT 0");
       
   477     }
       
   478 
       
   479     CX_DEBUG_EXIT_FUNCTION();
       
   480 }
       
   481 
       
   482 /*!
       
   483 * Handle ECAM events.
       
   484 * Needed only for capture sound synchronization.
       
   485 * @param eventUid ECAM event id.
       
   486 * @param error Error code. KErrNone if operation has been successful.
       
   487 */
       
   488 void CxeStillCaptureControlSymbian::handleCameraEvent(int eventUid, int error)
       
   489 {
       
   490     if (eventUid == KUidECamEventImageCaptureEventUidValue && error == KErrNone) {
       
   491         CX_DEBUG(("CxeStillCaptureControlSymbian::handleCameraEvent - image capture event"));
       
   492         if (state() == CxeStillCaptureControl::Capturing) {
       
   493             mCaptureSoundPlayer->play();
       
   494         }
       
   495     }
       
   496 }
       
   497 
       
   498 
       
   499 /*!
       
   500  * handleImageData: Image data received from ECam
       
   501  */
       
   502 void CxeStillCaptureControlSymbian::handleImageData(MCameraBuffer* cameraBuffer, int error)
       
   503 {
       
   504     CX_DEBUG_ENTER_FUNCTION();
       
   505 
       
   506     if (state() == CxeStillCaptureControl::Uninitialized) {
       
   507         // we ignore this event, when we are not active
       
   508         cameraBuffer->Release();
       
   509         return;
       
   510     }
       
   511 
       
   512     // Get image container for current image data index.
       
   513     // Remember to increment counter.
       
   514     CxeStillImageSymbian* stillImage = getImageForIndex(mNextImageDataIndex++);
       
   515 
       
   516     if (error) {
       
   517         // Indicate error in image capture to the UI.
       
   518         cameraBuffer->Release();
       
   519         emit imageCaptured(CxeErrorHandlingSymbian::map(error), stillImage->id());
       
   520         return;
       
   521     }
       
   522 
       
   523     // If filename is not available at this stage, then generate one now
       
   524     if (stillImage->filename().isEmpty()) {
       
   525         CxeError::Id cxErr = prepareFilename(stillImage);
       
   526         if (cxErr) {
       
   527             cameraBuffer->Release();
       
   528             emit imageCaptured(cxErr, stillImage->id());
       
   529             return;
       
   530         }
       
   531     }
       
   532 
       
   533     // Get the image data from the buffer
       
   534     TDesC8* data = NULL;
       
   535     TRAPD( symbErr, data = cameraBuffer->DataL(0) );
       
   536     CX_DEBUG(("dataError: %d, data: 0x%08x", symbErr, data));
       
   537 
       
   538     if (!data && !symbErr) {
       
   539         symbErr = KErrNoMemory;
       
   540     }
       
   541 
       
   542     // If data is available, initiate saving of image
       
   543     if (!symbErr) {
       
   544         //! @todo: this does a deep copy... we want to avoid this for performance/memory consumption reasons
       
   545         QByteArray byteArray( reinterpret_cast<const char*>( data->Ptr() ), data->Size() );
       
   546         data = NULL;
       
   547 
       
   548         // get geotagging setting value and check if we have to add location trail to image data.
       
   549         Cxe::GeoTagging value = mSettings.get<Cxe::GeoTagging>(CxeSettingIds::GEOTAGGING, Cxe::GeoTaggingOff);
       
   550 
       
   551 
       
   552         // Save the image data
       
   553         CxeImageDataItemSymbian* dataItem = mImageDataQueue->startSave(byteArray,
       
   554                                                                        stillImage->filename(),
       
   555                                                                        stillImage->id(),
       
   556                                                                        value == Cxe::GeoTaggingOn);
       
   557         stillImage->setDataItem(dataItem);
       
   558         mFileSaveThread.save(dataItem); // Saving thread takes ownership of dataItem.
       
   559     }
       
   560 
       
   561     // ECam Camera buffer should always be released
       
   562     cameraBuffer->Release();
       
   563 
       
   564     // Inform interested parties about image capture
       
   565     emit imageCaptured(CxeErrorHandlingSymbian::map(symbErr), stillImage->id());
       
   566 
       
   567     // set state to ready, since capturing is complete
       
   568     setState(Ready);
       
   569 
       
   570     // image capture ready, before that we check if the orientation of the device changed during capture and if so, we set the new orientation
       
   571     setOrientation(mSensorEventHandler.sensorData(CxeSensorEventHandler::OrientationSensor));
       
   572 
       
   573     CX_DEBUG_EXIT_FUNCTION();
       
   574 }
       
   575 
       
   576 
       
   577 /*!
       
   578  * Settings changed, needs updated
       
   579  */
       
   580 void CxeStillCaptureControlSymbian::handleSettingValueChanged(const QString& settingId, QVariant newValue)
       
   581 {
       
   582     CX_DEBUG_ENTER_FUNCTION();
       
   583 
       
   584     Q_UNUSED(newValue);
       
   585 
       
   586     if (settingId == CxeSettingIds::IMAGE_QUALITY) {
       
   587         // re-prepare for still
       
   588         if (state() == Ready) {
       
   589             deinit();
       
   590             init();
       
   591         }
       
   592     }
       
   593 
       
   594     CX_DEBUG_EXIT_FUNCTION();
       
   595 }
       
   596 
       
   597 /*!
       
   598 * Disk space changed.
       
   599 * Emit remaining images changed signal, if space change affects it.
       
   600 */
       
   601 void CxeStillCaptureControlSymbian::handleDiskSpaceChanged()
       
   602 {
       
   603     CX_DEBUG_ENTER_FUNCTION();
       
   604 
       
   605     // Ignore updates on other states.
       
   606     if (state() == CxeStillCaptureControl::Ready) {
       
   607 
       
   608         int images = calculateRemainingImages(mCurrentImageDetails.mEstimatedSize);
       
   609 
       
   610         if (images != mCurrentImageDetails.mPossibleImages) {
       
   611             CX_DEBUG(("CxeStillCaptureControlSymbian - available images changed %d -> %d",
       
   612                       mCurrentImageDetails.mPossibleImages, images));
       
   613 
       
   614             mCurrentImageDetails.mPossibleImages = images;
       
   615             emit availableImagesChanged();
       
   616         }
       
   617     }
       
   618 
       
   619     CX_DEBUG_EXIT_FUNCTION();
       
   620 }
       
   621 
       
   622 /*!
       
   623  * ECam reference changing, release resources
       
   624  */
       
   625 void CxeStillCaptureControlSymbian::prepareForCameraDelete()
       
   626 {
       
   627     CX_DEBUG_ENTER_FUNCTION();
       
   628     deinit();
       
   629     CX_DEBUG_EXIT_FUNCTION();
       
   630 }
       
   631 
       
   632 /*!
       
   633  * Camera being released. Cancel ongoing capture, if any.
       
   634  */
       
   635 void CxeStillCaptureControlSymbian::prepareForRelease()
       
   636 {
       
   637     CX_DEBUG_ENTER_FUNCTION();
       
   638     deinit();
       
   639     CX_DEBUG_EXIT_FUNCTION();
       
   640 }
       
   641 
       
   642 /*!
       
   643  *  New camera available,
       
   644  */
       
   645 void CxeStillCaptureControlSymbian::handleCameraAllocated(CxeError::Id error)
       
   646 {
       
   647     CX_DEBUG_ENTER_FUNCTION();
       
   648 
       
   649     if (error == CxeError::None) {
       
   650         // load all still resoultions supported by ecam
       
   651         mECamSupportedImageResolutions.clear();
       
   652         TCameraInfo cameraInfo;
       
   653         Cxe::CameraIndex cameraIndex = mCameraDeviceControl.cameraIndex();
       
   654         CCamera::TFormat imgFormat = supportedStillFormat(cameraIndex);
       
   655         mCameraDevice.camera()->CameraInfo(cameraInfo);
       
   656 
       
   657         for(int i = 0; i < cameraInfo.iNumImageSizesSupported; i++) {
       
   658             TSize size;
       
   659             mCameraDevice.camera()->EnumerateCaptureSizes(size, i, imgFormat);
       
   660             CX_DEBUG(("ECam supported resolution <> Size (%d): (%d,%d)", i, size.iWidth, size.iHeight));
       
   661             mECamSupportedImageResolutions.insert(i, size);
       
   662         }
       
   663 
       
   664         // load all still qualities supported by icm
       
   665         mIcmSupportedImageResolutions.clear();
       
   666         // get list of supported image qualities based on camera index
       
   667         mIcmSupportedImageResolutions = mQualityPresets.imageQualityPresets(cameraIndex);
       
   668 
       
   669         CX_DEBUG(("ECAM Supported Qualities count = %d", mECamSupportedImageResolutions.count()));
       
   670         CX_DEBUG(("ICM Supported Qualities count = %d", mIcmSupportedImageResolutions.count()));
       
   671     }
       
   672 
       
   673     CX_DEBUG_EXIT_FUNCTION();
       
   674 }
       
   675 
       
   676 /*!
       
   677  * Return number of images captured (during current capture operation only).
       
   678  */
       
   679 int CxeStillCaptureControlSymbian::imageCount() const
       
   680 {
       
   681     return mImages.count();
       
   682 }
       
   683 
       
   684 /*!
       
   685  * Reset the image array.
       
   686  */
       
   687 void CxeStillCaptureControlSymbian::reset()
       
   688 {
       
   689     CX_DEBUG_ENTER_FUNCTION();
       
   690 
       
   691     qDeleteAll( mImages );
       
   692     mImages.clear();
       
   693 
       
   694     mNextSnapshotIndex = 0;
       
   695     mNextImageDataIndex = 0;
       
   696 
       
   697     CX_DEBUG_EXIT_FUNCTION();
       
   698 }
       
   699 
       
   700 /*!
       
   701  * This should cancel any ongoing image captures.
       
   702  */
       
   703 void CxeStillCaptureControlSymbian::cancelAll()
       
   704 {
       
   705     mImageDataQueue->clear();
       
   706     reset();
       
   707 }
       
   708 
       
   709 /*!
       
   710  * Sets the current capture mode: SingleImageCapture / BurstCapture.
       
   711  */
       
   712 void CxeStillCaptureControlSymbian::setMode( CaptureMode mode )
       
   713 {
       
   714     mMode = mode;
       
   715 }
       
   716 
       
   717 /*!
       
   718  * Returns the current capture mode.
       
   719  */
       
   720 CxeStillCaptureControl::CaptureMode CxeStillCaptureControlSymbian::mode() const
       
   721 {
       
   722     return mMode;
       
   723 }
       
   724 
       
   725 /*!
       
   726  * Operator [] - returns the indexed image from capture array.
       
   727  */
       
   728 CxeStillImage &CxeStillCaptureControlSymbian::operator[]( int index )
       
   729 {
       
   730     return *mImages[ index ];
       
   731 }
       
   732 
       
   733 /*!
       
   734  * Getter for image data queue.
       
   735  */
       
   736 CxeImageDataQueue &CxeStillCaptureControlSymbian::imageDataQueue()
       
   737 {
       
   738     return *mImageDataQueue;
       
   739 }
       
   740 
       
   741 /*!
       
   742  * Generates a filename and sets it in the still image object.
       
   743  * Skips the process if filename already copied exists in the object. This
       
   744  * behaviour is required in rare cases where image data arrives before snapshot.
       
   745  */
       
   746 CxeError::Id
       
   747 CxeStillCaptureControlSymbian::prepareFilename(CxeStillImageSymbian *stillImage)
       
   748 {
       
   749     OstTrace0(camerax_performance, CXESTILLCAPTURECONTROLSYMBIAN_PREPAREFILENAME_1, "msg: e_CX_PREPARE_FILENAME 1" );
       
   750 
       
   751     CxeError::Id err = CxeError::None;
       
   752     if (stillImage->filename().isEmpty()) {
       
   753         QString path;
       
   754 
       
   755         QString fileExt = mCurrentImageDetails.mImageFileExtension;
       
   756 
       
   757         if (mMode == SingleImageCapture) {
       
   758             err = mFilenameGenerator.generateFilename(path, fileExt);
       
   759         }
       
   760         else {
       
   761             err = mFilenameGenerator.nextImageFilenameInSequence(path, fileExt);
       
   762         }
       
   763 
       
   764         if (!err) {
       
   765             CX_DEBUG(( "Next image file path: %s", path.toAscii().constData() ));
       
   766             stillImage->setFilename(path);
       
   767         }
       
   768         else {
       
   769             //! @todo: Error ID can be returned by this function.
       
   770             // Also error can be detected from empty filename string.
       
   771             CX_DEBUG(("ERROR in filename generation. err:%d", err));
       
   772         }
       
   773     }
       
   774 
       
   775     OstTrace0(camerax_performance, CXESTILLCAPTURECONTROLSYMBIAN_PREPAREFILENAME_2, "msg: e_CX_PREPARE_FILENAME 0" );
       
   776     return err;
       
   777 }
       
   778 
       
   779 /*!
       
   780 * Helper method to set orientation data from the orientation sensor
       
   781 */
       
   782 void CxeStillCaptureControlSymbian::setOrientation(QVariant sensorData)
       
   783 {
       
   784     CX_DEBUG_ENTER_FUNCTION();
       
   785 
       
   786     if (mCameraDevice.cameraOrientation() && state() == Ready) {
       
   787         Cxe::DeviceOrientation uiOrientation = qVariantValue<Cxe::DeviceOrientation >(sensorData);
       
   788         MCameraOrientation::TOrientation currentCameraOrientation = mCameraDevice.cameraOrientation()->Orientation();
       
   789         MCameraOrientation::TOrientation newCameraOrientation = CxeSettingsMapperSymbian::Map2CameraOrientation(uiOrientation);
       
   790 
       
   791         CX_DEBUG((("cameraindex: %d mMode: %d state(): %d mAfState: %d uiOrientation: %d "),mCameraDeviceControl.cameraIndex(),
       
   792                 mMode, state(), mAfState, uiOrientation ));
       
   793         if (mCameraDeviceControl.cameraIndex() == Cxe::PrimaryCameraIndex &&
       
   794             mMode                              == SingleImageCapture &&
       
   795             uiOrientation                      != Cxe::OrientationNone &&
       
   796             currentCameraOrientation           != newCameraOrientation &&
       
   797            (mAfState                           == CxeAutoFocusControl::Unknown ||
       
   798             mAfState                           == CxeAutoFocusControl::Canceling)
       
   799         ) {
       
   800             CX_DEBUG(("Setting Orientation to adaptation"));
       
   801             TRAP_IGNORE(mCameraDevice.cameraOrientation()->SetOrientationL(newCameraOrientation));
       
   802         }
       
   803     }
       
   804 
       
   805     CX_DEBUG_EXIT_FUNCTION();
       
   806 }
       
   807 
       
   808 /*!
       
   809  * Get the image container at given index or create a new one if needed.
       
   810  */
       
   811 CxeStillImageSymbian* CxeStillCaptureControlSymbian::getImageForIndex(int index)
       
   812 {
       
   813     CxeStillImageSymbian* image(NULL);
       
   814 
       
   815     if (mImages.count() <= index) {
       
   816         image = new CxeStillImageSymbian();
       
   817         mImages.append(image);
       
   818     } else {
       
   819         CX_DEBUG_ASSERT( mNextImageDataIndex >= 0 && index < mImages.count() );
       
   820         image = mImages[index];
       
   821     }
       
   822     return image;
       
   823 }
       
   824 
       
   825 
       
   826 /*!
       
   827 * Slot to handle Autofocus events.
       
   828 * \param newState Indicates current state of the auto focus
       
   829 * \param error Contains possible error code
       
   830 */
       
   831 void CxeStillCaptureControlSymbian::handleAutofocusStateChanged(
       
   832                                          CxeAutoFocusControl::State newState,
       
   833                                          CxeError::Id error )
       
   834 {
       
   835     CX_DEBUG_ENTER_FUNCTION();
       
   836     Q_UNUSED(error);
       
   837     mAfState = newState;
       
   838     CxeAutoFocusControl::Mode mode = mAutoFocusControl.mode();
       
   839 
       
   840     // if focused and in correct mode, play sound
       
   841     if  (newState == CxeAutoFocusControl::Ready &&
       
   842          !mAutoFocusControl.isFixedFocusMode(mode) &&
       
   843          mAutoFocusControl.isSoundEnabled()) {
       
   844         mAutoFocusSoundPlayer->play();
       
   845     }
       
   846     CX_DEBUG_EXIT_FUNCTION();
       
   847 }
       
   848 
       
   849 
       
   850 /*!
       
   851 * Slot that sets orientation data emited from orientation sensor
       
   852 */
       
   853 void CxeStillCaptureControlSymbian::handleSensorEvent(
       
   854                                 CxeSensorEventHandler::SensorType type,
       
   855                                 QVariant data)
       
   856 {
       
   857     CX_DEBUG_ENTER_FUNCTION();
       
   858 
       
   859     if (type == CxeSensorEventHandler::OrientationSensor) {
       
   860         setOrientation(data);
       
   861     } else {
       
   862         // nothing to do
       
   863     }
       
   864 
       
   865     CX_DEBUG_EXIT_FUNCTION();
       
   866 }
       
   867 
       
   868 
       
   869 /*!
       
   870     Use ECam Use Case Hint Custom API to inform ECam of our intended use case
       
   871     before calling Reserve().
       
   872 */
       
   873 void CxeStillCaptureControlSymbian::hintUseCase()
       
   874 {
       
   875     CX_DEBUG_ENTER_FUNCTION();
       
   876 
       
   877     // Make sure ECam knows we're doing still image capture so it can prepare
       
   878     // for the correct use case.
       
   879     if (mCameraDeviceControl.mode() == Cxe::ImageMode) {
       
   880         MCameraUseCaseHint *useCaseHintApi = mCameraDevice.useCaseHintApi();
       
   881         if (useCaseHintApi) {
       
   882             updateStillCaptureParameters();
       
   883             TRAP_IGNORE(useCaseHintApi->HintStillCaptureL(mCaptureFormat,
       
   884                                                           mSizeIndex));
       
   885         }
       
   886     }
       
   887 
       
   888     CX_DEBUG_EXIT_FUNCTION();
       
   889 }
       
   890 
       
   891 /*!
       
   892 * Returns supported image qualities based on the camera index
       
   893 * (primary/secondary).
       
   894 */
       
   895 QList<CxeImageDetails> CxeStillCaptureControlSymbian::supportedImageQualities()
       
   896 {
       
   897     // update remaining images counter
       
   898     updateRemainingImagesCounter();
       
   899 
       
   900     return mIcmSupportedImageResolutions;
       
   901 }
       
   902 
       
   903 
       
   904 /*!
       
   905 * Updates remaining images counter to all the image qualities supported by ICM
       
   906 * this should be done whenever storage location setting changes and when values are
       
   907 * read from ICM for the first time
       
   908 */
       
   909 void CxeStillCaptureControlSymbian::updateRemainingImagesCounter()
       
   910 {
       
   911     CX_DEBUG_ENTER_FUNCTION();
       
   912 
       
   913     for( int index = 0; index < mIcmSupportedImageResolutions.count(); index++) {
       
   914         CxeImageDetails &qualityDetails = mIcmSupportedImageResolutions[index];
       
   915         qualityDetails.mPossibleImages = calculateRemainingImages(qualityDetails.mEstimatedSize);
       
   916     }
       
   917 
       
   918     CX_DEBUG_EXIT_FUNCTION();
       
   919 }
       
   920 
       
   921 
       
   922 /*!
       
   923 * Returns the number of images left for the current image quality setting
       
   924 */
       
   925 int CxeStillCaptureControlSymbian::imagesLeft()
       
   926 {
       
   927     CX_DEBUG_ENTER_FUNCTION();
       
   928 
       
   929     if (mCurrentImageDetails.mPossibleImages == CxeImageDetails::UNKNOWN) {
       
   930         mCurrentImageDetails.mPossibleImages = calculateRemainingImages(mCurrentImageDetails.mEstimatedSize);
       
   931     }
       
   932 
       
   933     CX_DEBUG_EXIT_FUNCTION();
       
   934     return mCurrentImageDetails.mPossibleImages;
       
   935 }
       
   936 
       
   937 
       
   938 
       
   939 /*!
       
   940 * CxeStillCaptureControlSymbian::calculateRemainingImages
       
   941 @ param estimatedImagesize, the estimated size for image resolution
       
   942 @ returns number of images remaining
       
   943 */
       
   944 int
       
   945 CxeStillCaptureControlSymbian::calculateRemainingImages(int estimatedImagesize)
       
   946 {
       
   947     CX_DEBUG_ENTER_FUNCTION();
       
   948 
       
   949     qint64 space = mDiskMonitor.free() - KMinRequiredSpaceImage;
       
   950     int images = std::max(qint64(0), space / estimatedImagesize);
       
   951 
       
   952     CX_DEBUG_EXIT_FUNCTION();
       
   953 
       
   954     return images;
       
   955 }
       
   956 
       
   957 // end of file