diff -r 0e652f8f1fbd -r 24fd82631616 camerauis/cameraxui/cxengine/src/cxestillcapturecontroldesktop.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/camerauis/cameraxui/cxengine/src/cxestillcapturecontroldesktop.cpp Fri Jul 23 11:35:41 2010 +0300 @@ -0,0 +1,594 @@ +/* +* Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: +* +*/ + +#include + +#include "cxestillcapturecontroldesktop.h" +#include "cxeimagedataitemdesktop.h" +#include "cxeimagedataqueuedesktop.h" +#include "cxefilenamegenerator.h" +#include "cxefilesavethreaddesktop.h" +#include "cxutils.h" +#include "cxecameradevicecontrol.h" +#include "cxestillimagedesktop.h" +#include "cxeviewfindercontrol.h" +#include "cxeviewfindercontroldesktop.h" +#include "cxeautofocuscontrol.h" +#include "cxestate.h" +#include "cxecameradevicedesktop.h" + +// constants +const int KMaintainAspectRatio = false; + + + +/** + * Constructor. + */ +CxeStillCaptureControlDesktop::CxeStillCaptureControlDesktop( + CxeCameraDeviceDesktop &cameraDevice, + CxeViewfinderControl &viewfinderControl, + CxeCameraDeviceControl &cameraDeviceControl, + CxeFilenameGenerator &nameGenerator, + CxeAutoFocusControl &autoFocusControl, + CxeFileSaveThread &saveThread) : + mCameraDevice(cameraDevice), + mState(CxeStillCaptureControl::Uninitialized), + mViewfinderControl(viewfinderControl), + mCameraDeviceControl(cameraDeviceControl), + mFilenameGenerator(nameGenerator), + mAutoFocusControl(autoFocusControl), + mMode(SingleImageCapture), + mAfState(CxeAutoFocusControl::Unknown), + mSaveThread(saveThread) +{ + CX_DEBUG_ENTER_FUNCTION(); + + qRegisterMetaType(); + initializeStates(); + reset(); + + mImageDataQueue = new CxeImageDataQueueDesktop(); + + CX_DEBUG_EXIT_FUNCTION(); +} + +/** + * Destructor. + */ +CxeStillCaptureControlDesktop::~CxeStillCaptureControlDesktop() +{ + CX_DEBUG_ENTER_FUNCTION(); + + deinit(); + reset(); + mSupportedImageQualities.clear(); + delete mImageDataQueue; + + CX_DEBUG_EXIT_FUNCTION(); +} + +/** + * Return the current state. + */ +CxeStillCaptureControl::State CxeStillCaptureControlDesktop::state() const +{ + return mState; +} + +/** + * Initialize the control states. + */ +void CxeStillCaptureControlDesktop::initializeStates() +{ + + // addState( id, name, allowed next states ) +} + +/** + * Initialize the still image capture control. + */ +void CxeStillCaptureControlDesktop::init() +{ + CX_DEBUG_ENTER_FUNCTION(); + + if (state() == Uninitialized) { + CxeImageDetails dummyDetails; + dummyDetails.mAspectRatio = Cxe::AspectRatio4to3; + dummyDetails.mEstimatedSize = 10000; + dummyDetails.mHeight = 360; + dummyDetails.mWidth = 640; + mSupportedImageQualities.append(dummyDetails); + prepare(); + } + + CX_DEBUG_EXIT_FUNCTION(); +} + +/** + * Un-initialize the image mode. + */ +void CxeStillCaptureControlDesktop::deinit() +{ + CX_DEBUG_ENTER_FUNCTION(); + + if (state() == Uninitialized) { + // nothing to do + CX_DEBUG_EXIT_FUNCTION(); + return; + } + mState = Uninitialized; + CX_DEBUG_EXIT_FUNCTION(); +} + + +/*! + * Prepare still capture mode. + */ +void CxeStillCaptureControlDesktop::prepare() +{ + CX_DEBUG_ENTER_FUNCTION(); + + if (state() != Uninitialized) { + // wrong state and we return + return; + } + + int err = 0; + CxeError::Id cxErr = getImageQualityDetails(mCurrentImageDetails); + int ecamStillResolutionIndex = 0; + + if (cxErr == CxeError::None) { + int imageWidth = mCurrentImageDetails.mWidth; + int imageHeight = mCurrentImageDetails.mHeight; + CX_DEBUG(("CxeStillCaptureControlSymbian::prepare <> resolution = (%d, %d)", imageWidth, imageHeight)); + + if (ecamStillResolutionIndex < 0) { + CX_DEBUG(("CxeStillCaptureControlSymbian::prepare - WARNING! resolution not supported, falling back to index 0")); + ecamStillResolutionIndex = 0; + } + + CX_DEBUG(("PrepareImageCaptureL done, err=%d, resolution index = %d", err, ecamStillResolutionIndex)); + + if (!err) { + // still capture prepare went fine, try preparing snapshot + err = prepareStillSnapshot(); + } + } else { + err = 0; + } + + if (!err) { + // If viewfinder is already running, this call does nothing + mViewfinderControl.start(); + // inform zoom control to prepare zoom + emit prepareZoomForStill(ecamStillResolutionIndex); + } else { + CX_DEBUG(("Image Prepare FAILED! symbian error = %d", err)); + } + mState = Ready; + emit imagePrepareComplete(CxeError::None); + CX_DEBUG_EXIT_FUNCTION(); +} + + + +/*! + Prepare still snapshot + Returns symbian error code. + */ +int CxeStillCaptureControlDesktop::prepareStillSnapshot() +{ + CX_DEBUG_ENTER_FUNCTION(); + + handleSnapshotEvent(CxeError::None); + + CX_DEBUG_EXIT_FUNCTION(); + + return 0; +} + + +/*! + imageInfo contains image qualities details + Returns CxeError error code. + */ +CxeError::Id CxeStillCaptureControlDesktop::getImageQualityDetails(CxeImageDetails &imageInfo) +{ + CX_DEBUG_ENTER_FUNCTION(); + + int imageQuality = 0; + CxeError::Id err = CxeError::None; + if (mCameraDeviceControl.cameraIndex() == Cxe::PrimaryCameraIndex) { + bool validQuality = (imageQuality >= 0 && imageQuality < mSupportedImageQualities.count()); + + if (err == CxeError::None && validQuality ) { + // get image quality details + imageInfo = mSupportedImageQualities.at(imageQuality); + } else { + err = CxeError::NotFound; + CX_DEBUG(("Invalid ImageQuality = %d", imageQuality)); + } + } else { + // we are in secondary camera + // get secondary camera image quality details + imageInfo = mSupportedImageQualities.at(imageQuality); + } + + CX_DEBUG_EXIT_FUNCTION(); + return err; +} + + +/** + * Command to start image capture now. + */ +void CxeStillCaptureControlDesktop::capture() +{ + CX_DEBUG_ENTER_FUNCTION(); + + //! @todo: NOTE: This call may not stay here. It can move depending on the implementation for burst capture. + if (mMode == BurstCapture) { + // Start a new filename sequence + mFilenameGenerator.startNewImageFilenameSequence(); + } + emit imageCaptured(CxeError::None, 0); + handleSnapshotEvent(CxeError::None); + CX_DEBUG_EXIT_FUNCTION(); +} + + +/** + * Snapshot ready notification. Ask the snapshot from snapshot interface. + * NB: Typically snapshot arrives before image data but can be in reverse + * order as well. + */ +void CxeStillCaptureControlDesktop::handleSnapshotEvent(CxeError::Id error) +{ + CX_DEBUG_ENTER_FUNCTION(); + + if (state() == CxeStillCaptureControl::Uninitialized) { + // we ignore this event, when we are not active + return; + } + + if (error) { + emit snapshotReady(error, QImage(), 0); + } + + // Get image container for current snapshot index. + // Remember to increment counter. + CxeStillImageDesktop* stillImage = getImageForIndex(mNextSnapshotIndex++); + + // When the snapshot ready event is handled, prepare new filename. + if (stillImage->filename().isEmpty()) { + // Error ignored at this point, try again when image data arrives. + prepareFilename(stillImage); + } + + CxeImageDataItem* dataItem = new CxeImageDataItemDesktop(mNextImageDataIndex++, stillImage->snapshot(), stillImage->filename(), stillImage->id()); + + stillImage->setDataItem(dataItem); + + mSaveThread.save(dataItem); + + emit snapshotReady(CxeError::None, QImage(), stillImage->id()); + emit imageCaptured(CxeError::None, stillImage->id()); + + mState = Ready; + emit stateChanged(mState, CxeError::None); + + CX_DEBUG_EXIT_FUNCTION(); +} + + + +/** + * Settings changed, needs updated + */ +void CxeStillCaptureControlDesktop::handleSettingValueChanged(const QString& settingId,QVariant newValue) +{ + CX_DEBUG_ENTER_FUNCTION(); + + if (settingId == CxeSettingIds::FLASH_MODE) { + updateFlashSetting(newValue); + } else if (settingId == CxeSettingIds::LIGHT_SENSITIVITY) { + updateISOSetting(newValue); + } else if (settingId == CxeSettingIds::EV_COMPENSATION_VALUE) { + updateEVCompensationSetting(newValue); + } else if (settingId == CxeSettingIds::IMAGE_QUALITY) { + // re-prepare for still + deinit(); + init(); + } else { + // do nothing + } + CX_DEBUG_EXIT_FUNCTION(); +} + +/** + * Image Scene mode changed, needs updated + */ +void CxeStillCaptureControlDesktop::handleSceneChanged(CxeScene& scene) +{ + CX_DEBUG_ENTER_FUNCTION(); + + if (mCameraDeviceControl.cameraIndex() == Cxe::PrimaryCameraIndex){ + CX_DEBUG_ASSERT(scene.count() != 0); + // we are interested only in the following settings in this class scope + + if(scene.contains(CxeSettingIds::FLASH_MODE)) { + CX_DEBUG(("CxeStillCaptureControlSymbian::handleSceneChanged scene->mFlashMode = %d", scene[CxeSettingIds::FLASH_MODE].toInt())); + updateFlashSetting(scene[CxeSettingIds::FLASH_MODE]); + } + + if(scene.contains(CxeSettingIds::LIGHT_SENSITIVITY)) { + updateISOSetting(scene[CxeSettingIds::LIGHT_SENSITIVITY]); + } + + if(scene.contains(CxeSettingIds::EV_COMPENSATION_VALUE)) { + updateEVCompensationSetting(scene[CxeSettingIds::EV_COMPENSATION_VALUE]); + } + } + + CX_DEBUG_EXIT_FUNCTION(); +} + +/** + * UpdateFlashSetting + */ +void CxeStillCaptureControlDesktop::updateFlashSetting(QVariant newValue) +{ + CX_DEBUG_ENTER_FUNCTION(); + + Q_UNUSED(newValue); + + CX_DEBUG_EXIT_FUNCTION(); +} + +/** + * UpdateISOSetting + */ +void CxeStillCaptureControlDesktop::updateISOSetting(QVariant newValue) +{ + CX_DEBUG_ENTER_FUNCTION(); + + Q_UNUSED(newValue); + + CX_DEBUG_EXIT_FUNCTION(); +} + +/** + * UpdateEVCompensationSetting + */ +void CxeStillCaptureControlDesktop::updateEVCompensationSetting(QVariant newValue) +{ + CX_DEBUG_ENTER_FUNCTION(); + + Q_UNUSED(newValue); + + + CX_DEBUG_EXIT_FUNCTION(); +} + + +/** + * ECam reference changing, release resources + */ +void CxeStillCaptureControlDesktop::prepareForCameraDelete() +{ + CX_DEBUG_ENTER_FUNCTION(); + deinit(); + CX_DEBUG_EXIT_FUNCTION(); +} + +/** + * Camera being released. Cancel ongoing capture, if any. + */ +void CxeStillCaptureControlDesktop::prepareForRelease() +{ + CX_DEBUG_ENTER_FUNCTION(); + deinit(); + CX_DEBUG_EXIT_FUNCTION(); +} + +/** + * New camera available, + */ +void CxeStillCaptureControlDesktop::handleCameraAllocated(CxeError::Id error) +{ + CX_DEBUG_ENTER_FUNCTION(); + + if (error == CxeError::None) { + // load all still resoultions supported by ecam + // load all still qualities supported by icm + mSupportedImageQualities.clear(); + // get list of supported image qualities based on camera index + + } + + CX_DEBUG_EXIT_FUNCTION(); +} + +/** + * Return number of images captured (during current capture operation only). + */ +int CxeStillCaptureControlDesktop::imageCount() const +{ + return mImages.count(); +} + +/** + * Reset the image array. + */ +void CxeStillCaptureControlDesktop::reset() +{ + CX_DEBUG_ENTER_FUNCTION(); + + qDeleteAll(mImages); + mImages.clear(); + + mNextSnapshotIndex = 0; + mNextImageDataIndex = 0; + + CX_DEBUG_EXIT_FUNCTION(); +} + +/** + * This should cancel any ongoing image captures. + */ +void CxeStillCaptureControlDesktop::cancelAll() +{ + mImageDataQueue->clear(); + reset(); +} + +/** + * Sets the current capture mode: SingleImageCapture / BurstCapture. + */ +void CxeStillCaptureControlDesktop::setMode(CaptureMode mode) +{ + mMode = mode; +} + +/** + * Returns the current capture mode. + */ +CxeStillCaptureControl::CaptureMode CxeStillCaptureControlDesktop::mode() const +{ + return mMode; +} + +/** + * Operator [] - returns the indexed image from capture array. + */ +CxeStillImage &CxeStillCaptureControlDesktop::operator[](int index) +{ + return *mImages[ index ]; +} + +/** + * Getter for image data queue. + */ +CxeImageDataQueue &CxeStillCaptureControlDesktop::imageDataQueue() +{ + return *mImageDataQueue; +} + +/** + * Generates a filename and sets it in the still image object. + * Skips the process if filename already copied exists in the object. This + * behaviour is required in rare cases where image data arrives before snapshot. + */ +CxeError::Id CxeStillCaptureControlDesktop::prepareFilename(CxeStillImageDesktop *stillImage) +{ + CxeError::Id err = CxeError::None; + if (stillImage->filename().isEmpty()) { + QString path; + + QString fileExt = mCurrentImageDetails.mImageFileExtension; + + if (mMode == SingleImageCapture) { + err = mFilenameGenerator.generateFilename(path, fileExt); + } + else { + err = mFilenameGenerator.nextImageFilenameInSequence(path, fileExt); + } + + if (!err) { + CX_DEBUG(( "Next image file path: %s", path.toAscii().constData() )); + stillImage->setFilename(path); + } + else { + //! @todo: Error ID can be returned by this function. + // Also error can be detected from empty filename string. + CX_DEBUG(("ERROR in filename generation. err:%d", err)); + } + } + return err; +} + +/*! +* Helper method to set orientation data from the orientation sensor +*/ +void CxeStillCaptureControlDesktop::setOrientation(QVariant sensorData) +{ + CX_DEBUG_ENTER_FUNCTION(); + + Q_UNUSED(sensorData); + + CX_DEBUG_EXIT_FUNCTION(); +} + +/** + * Get the image container at given index or create a new one if needed. + */ +CxeStillImageDesktop* CxeStillCaptureControlDesktop::getImageForIndex(int index) +{ + CxeStillImageDesktop* image(NULL); + + if (mImages.count() <= index) { + image = new CxeStillImageDesktop(); + image->setSnapshot(mCameraDevice.currentSnaphot()); + mImages.append(image); + } else { + CX_DEBUG_ASSERT( mNextImageDataIndex >= 0 && index < mImages.count() ); + image = mImages[index]; + } + return image; +} + + +/*! +* Slot to handle Autofocus events. +*/ +void CxeStillCaptureControlDesktop::handleAutofocusStateChanged( + CxeAutoFocusControl::State newState, + CxeError::Id /*error*/ ) +{ + CX_DEBUG_ENTER_FUNCTION(); + + mAfState = newState; + CxeAutoFocusControl::Mode mode = mAutoFocusControl.mode(); + + // if focused and in correct mode, play sound + if (newState == CxeAutoFocusControl::Ready && + mode != CxeAutoFocusControl::Hyperfocal && + mode != CxeAutoFocusControl::Infinity) { + } + CX_DEBUG_EXIT_FUNCTION(); +} + + +/*! +* Returns supported image qualities based on the camera index +* (primary/secondary). +*/ +QList CxeStillCaptureControlDesktop::supportedImageQualities() +{ + return QList(); +} + +/*! +* Returns the number of images left for the current image quality setting +*/ +int CxeStillCaptureControlDesktop::imagesLeft() +{ + return 100; // Stub: Dummy value +} + +// end of file