camerauis/cameraxui/cxengine/src/cxeenginesymbian.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Wed, 18 Aug 2010 09:37:18 +0300
changeset 48 42ba2d16bf40
parent 37 64817133cd1d
child 63 415ff50d2eca
permissions -rw-r--r--
Revision: 201031 Kit: 201033

/*
* Copyright (c) 2009-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 <xqserviceutil.h>

#include "cxeenginesymbian.h"
#include "cxecameradevicecontrolsymbian.h"
#include "cxestillcapturecontrolsymbian.h"
#include "cxevideocapturecontrolsymbian.h"
#include "cxesettingscontrolsymbian.h"
#include "cxeviewfindercontrolsymbian.h"
#include "cxesnapshotcontrol.h"
#include "cxefilenamegeneratorsymbian.h"
#include "cxeautofocuscontrolsymbian.h"
#include "cxezoomcontrolsymbian.h"
#include "cxequalitypresetssymbian.h"
#include "cxutils.h"
#include "cxesettingsimp.h"
#include "cxefeaturemanagerimp.h"
#include "cxesettingscenrepstore.h"
#include "cxesoundplayersymbian.h"
#include "cxesensoreventhandlersymbian.h"
#include "cxefilesavethread.h"
#include "cxecameradevice.h"
#include "cxememorymonitor.h"
#include "cxediskmonitor.h"
#include "cxegeotaggingtrail.h"
#include "cxeexception.h"

#include "OstTraceDefinitions.h"
#ifdef OST_TRACE_COMPILER_IN_USE
#include "cxeenginesymbianTraces.h"
#endif


//  Member Functions

CxeEngineSymbian::CxeEngineSymbian()
    : mCameraDeviceControl(NULL),
      mCameraDevice(NULL),
      mViewfinderControl(NULL),
      mSnapshotControl(NULL),
      mStillCaptureControl(NULL),
      mVideoCaptureControl(NULL),
      mSettingsControl(NULL),
      mAutoFocusControl(NULL),
      mZoomControl(NULL),
      mSettings(NULL),
      mFeatureManager(NULL),
      mFilenameGenerator(NULL),
      mSensorEventHandler(NULL),
      mQualityPresets(NULL),
      mFileSaveThread(NULL),
      mDiskMonitor(NULL),
      mMemoryMonitor(NULL),
      mGeoTaggingTrail(NULL)
{
    CX_DEBUG_IN_FUNCTION();
}


/*!
    Create all control classes and connect relevant signals
*/
void CxeEngineSymbian::construct()
{
    CX_DEBUG_ENTER_FUNCTION();

    createControls();
    connectSignals();

    CX_DEBUG_EXIT_FUNCTION();
}


/*!
    Create all control classes.
    Note: Throws an error, if free memory request by CxeMemoryMonitor constructor fails!
*/
void CxeEngineSymbian::createControls()
{
    CX_DEBUG_ENTER_FUNCTION();

    // Check we do this only once.
    if (!mSettings) {
        OstTrace0(camerax_performance, CXEENGINESYMBIAN_CREATECONTROLS_IN, "msg: e_CX_ENGINE_CREATE_CONTROLS 1");

        CxeCameraDeviceControlSymbian *deviceControl = new CxeCameraDeviceControlSymbian();
        mCameraDeviceControl = deviceControl;
        mCameraDevice = deviceControl->cameraDevice();

        CX_ASSERT_ALWAYS(mCameraDeviceControl);
        CX_ASSERT_ALWAYS(mCameraDevice);

        mCameraDeviceControl->init();

        CxeSettingsCenRepStore *settingsStore(NULL);
        if (XQServiceUtil::isService()) {
            settingsStore = new CxeSettingsLocalStore();
        } else {
            settingsStore = new CxeSettingsCenRepStore();
        }

        //ownership of settings store transferred to the settings
        mSettings = new CxeSettingsImp(settingsStore);

        // Loading current camera mode value from settings store and updating
		// devicecontrol
        Cxe::CameraMode cameraMode = Cxe::ImageMode;

        try {
            cameraMode = mSettings->get<Cxe::CameraMode>(CxeSettingIds::CAMERA_MODE);
        } catch (CxeException &e) {
            CX_DEBUG(("Failed to read camera mode from settings, using image mode. Error code: %d", e.error()));
        }

        // set current camera mode to devicecontrol.
        mCameraDeviceControl->setMode(cameraMode);

        //! @todo a temporary hack to change the startup sequence to avoid GOOM problems
        static_cast<CxeSettingsImp*>(mSettings)->loadSettings(mode());


        // Connect P&S key updates to settings signal.
        connect(settingsStore, SIGNAL(settingValueChanged(long int, unsigned long int, QVariant)),
                mSettings, SIGNAL(settingValueChanged(long int, unsigned long int, QVariant)));

        mFeatureManager = new CxeFeatureManagerImp(*mSettings);

        // Memory monitor needed as early as possible to request free memory.
        // Note: Throws error if enough memory cannot be freed!
        mMemoryMonitor = new CxeMemoryMonitor(*mFeatureManager);

        mDiskMonitor = new CxeDiskMonitor(*mSettings);

        mQualityPresets = new CxeQualityPresetsSymbian(*mSettings);
        CX_DEBUG_ASSERT(mQualityPresets);

        // sensor event handler initialization
        mSensorEventHandler = new CxeSensorEventHandlerSymbian();

        mFilenameGenerator = new CxeFilenameGeneratorSymbian(*mSettings,
            mode());

        mViewfinderControl = new CxeViewfinderControlSymbian(*mCameraDevice,
            *mCameraDeviceControl);

        mSnapshotControl = new CxeSnapshotControl(*mCameraDevice);

        mAutoFocusControl = new CxeAutoFocusControlSymbian(*mCameraDevice,
		                            *mSettings);

        mFileSaveThread = CxeFileSaveThreadFactory::createFileSaveThread();

        mStillCaptureControl = new CxeStillCaptureControlSymbian(
            *mCameraDevice, *mViewfinderControl, *mSnapshotControl, *mCameraDeviceControl,
            *mFilenameGenerator, *mSensorEventHandler, *mAutoFocusControl,
            *mSettings, *mQualityPresets, *mFileSaveThread, *mDiskMonitor);

        mZoomControl = new CxeZoomControlSymbian(
            *mCameraDevice, *mCameraDeviceControl, *mSettings, *mFeatureManager);

        mVideoCaptureControl = new CxeVideoCaptureControlSymbian(
            *mCameraDevice, *mViewfinderControl, *mSnapshotControl, *mCameraDeviceControl,
            *mFilenameGenerator, *mSettings, *mQualityPresets, *mDiskMonitor);

        mSettingsControl = new CxeSettingsControlSymbian(*mCameraDevice, *mSettings);

        mGeoTaggingTrail = new CxeGeoTaggingTrail(*mStillCaptureControl,
                                                  *mVideoCaptureControl,
                                                  *mSettings);

        OstTrace0(camerax_performance, CXEENGINESYMBIAN_CREATECONTROLS_OUT, "msg: e_CX_ENGINE_CREATE_CONTROLS 0");
    }

    CX_DEBUG_EXIT_FUNCTION();
}

/*!
    Connect internal signals for control classes
*/
void CxeEngineSymbian::connectSignals()
{
    CX_DEBUG_ENTER_FUNCTION();
    OstTrace0(camerax_performance, CXEENGINESYMBIAN_CONNECTSIGNALS_IN, "msg: e_CX_ENGINE_CONNECT_SIGNALS 1");

    // enabling scene setting change callbacks to Autofocus control
    mSettings->listenForSetting(CxeSettingIds::IMAGE_SCENE_DATA, mAutoFocusControl, SLOT(handleSceneChanged(const QVariant&)));
    mSettings->listenForSetting(CxeSettingIds::VIDEO_SCENE_DATA, mAutoFocusControl, SLOT(handleSceneChanged(const QVariant&)));

    // connecting Autofocus state change callbacks to stillcapturecontrol
    connect(mAutoFocusControl,
            SIGNAL(stateChanged(CxeAutoFocusControl::State, CxeError::Id)),
            mStillCaptureControl,
            SLOT(handleAutofocusStateChanged(CxeAutoFocusControl::State,CxeError::Id)));

    // Connect signals for ECam events
    connect(mCameraDeviceControl,
            SIGNAL(cameraEvent(int,int)),
            mSnapshotControl,
            SLOT(handleCameraEvent(int,int)));

    connect(mCameraDeviceControl,
            SIGNAL(cameraEvent(int,int)),
            mAutoFocusControl,
            SLOT(handleCameraEvent(int,int)));

    connect(mCameraDeviceControl,
            SIGNAL(cameraEvent(int,int)),
            mStillCaptureControl,
            SLOT(handleCameraEvent(int,int)));

    // Connect signal for device ready events
    connect(mCameraDeviceControl,
            SIGNAL(deviceReady()),
            this,
            SLOT(doInit()));

    // Connect image and video init complete signals to
    // CameraDeviceControl initModeComplete
    connect(mStillCaptureControl,
            SIGNAL(imagePrepareComplete(CxeError::Id)),
            mCameraDeviceControl,
            SIGNAL(initModeComplete(CxeError::Id)));

    connect(mVideoCaptureControl,
            SIGNAL(videoPrepareComplete(CxeError::Id)),
            mCameraDeviceControl,
            SIGNAL(initModeComplete(CxeError::Id)));

    // Zoom is prepared once the image/video emits prepare zoom signals
    connect(mStillCaptureControl,
            SIGNAL(prepareZoomForStill(int)),
            mZoomControl,
            SLOT(prepareZoomForStill(int)));

    connect(mVideoCaptureControl,
            SIGNAL(prepareZoomForVideo()),
            mZoomControl,
            SLOT(prepareZoomForVideo()));

    // Connect file saving thread to snapshot signals and video saved signal.
    // Image saving it handles internally.
    connect(mStillCaptureControl,
            SIGNAL(snapshotReady(CxeError::Id, const QImage&, int)),
            mFileSaveThread,
            SLOT(handleSnapshotReady(CxeError::Id, const QImage&, int)));
    connect(mVideoCaptureControl,
            SIGNAL(videoComposed(CxeError::Id, const QString&)),
            mFileSaveThread,
            SLOT(handleVideoSaved(CxeError::Id, const QString&)));
    connect(mVideoCaptureControl,
            SIGNAL(snapshotReady(CxeError::Id, const QImage&, const QString&)),
            mFileSaveThread,
            SLOT(handleSnapshotReady(CxeError::Id, const QImage&, const QString&)));

    // stop location trail when releasing camera.
    connect(mCameraDevice,
            SIGNAL(prepareForRelease()),
            mGeoTaggingTrail,
            SLOT(stop()),
            Qt::UniqueConnection);

    // Use MCameraUseCaseHint API before calling Reserve()
    connect(mCameraDevice,
            SIGNAL(aboutToReserve()),
            mStillCaptureControl,
            SLOT(hintUseCase()),
            Qt::UniqueConnection);
    connect(mCameraDevice,
            SIGNAL(aboutToReserve()),
            mVideoCaptureControl,
            SLOT(hintUseCase()),
            Qt::UniqueConnection);

    // Start / stop geotagging based on mode.
    // Do this later to reduce startup time.
    connect(mStillCaptureControl,
            SIGNAL(imagePrepareComplete(CxeError::Id)),
            this,
            SLOT(initGeotagging()));
    connect(mVideoCaptureControl,
            SIGNAL(videoPrepareComplete(CxeError::Id)),
            this,
            SLOT(initGeotagging()));

    OstTrace0(camerax_performance, CXEENGINESYMBIAN_CONNECTSIGNALS_OUT, "msg: e_CX_ENGINE_CONNECT_SIGNALS 0");

    CX_DEBUG_EXIT_FUNCTION();
}

CxeEngineSymbian::~CxeEngineSymbian()
{
    CX_DEBUG_ENTER_FUNCTION();

    // Saving current camera mode to cenrep
    saveMode();

    delete mGeoTaggingTrail;
    delete mAutoFocusControl;
    delete mZoomControl;
    delete mSettingsControl;
    delete mStillCaptureControl;
    delete mVideoCaptureControl;
    delete mSnapshotControl;
    delete mViewfinderControl;
    delete mFilenameGenerator;
    delete mDiskMonitor;
    delete mMemoryMonitor;
    delete mFeatureManager;
    delete mSettings;
    delete mCameraDeviceControl;
    delete mQualityPresets;
    delete mFileSaveThread;

    CX_DEBUG_EXIT_FUNCTION();
}

CxeCameraDeviceControl &CxeEngineSymbian::cameraDeviceControl()
{
    return *mCameraDeviceControl;
}

CxeViewfinderControl &CxeEngineSymbian::viewfinderControl()
{
    return *mViewfinderControl;
}

CxeSnapshotControl &CxeEngineSymbian::snapshotControl()
{
    return *mSnapshotControl;
}

CxeStillCaptureControl &CxeEngineSymbian::stillCaptureControl()
{
    return *mStillCaptureControl;
}

CxeVideoCaptureControl &CxeEngineSymbian::videoCaptureControl()
{
    return *mVideoCaptureControl;
}

CxeAutoFocusControl &CxeEngineSymbian::autoFocusControl()
{
    return *mAutoFocusControl;
}

CxeZoomControl &CxeEngineSymbian::zoomControl()
{
    return *mZoomControl;
}

/*!
Returns the settings handle
*/
CxeSettings &CxeEngineSymbian::settings()
{
    return *mSettings;
}

/*!
Returns the sensor event  handle
*/
CxeSensorEventHandler &CxeEngineSymbian::sensorEventHandler()
{
    return *mSensorEventHandler;
}


CxeFeatureManager &CxeEngineSymbian::featureManager()
{
    return *mFeatureManager;
}

/*!
* Returns memory monitor utility handle.
*/
CxeMemoryMonitor &CxeEngineSymbian::memoryMonitor()
{
    return *mMemoryMonitor;
}


/*!
 Returns geotaggingtrail handle
 */
CxeGeoTaggingTrail &CxeEngineSymbian::geoTaggingTrail()
{
    return *mGeoTaggingTrail;
}

/*!
* Returns true, if the engine is ready or else false.
*/
bool CxeEngineSymbian::isEngineReady()
{
    bool ready = false;
    if (mCameraDeviceControl->state() == CxeCameraDeviceControl::Ready &&
        mViewfinderControl->state() == CxeViewfinderControl::Running) {
        if (mode() == Cxe::ImageMode) {
            if (mStillCaptureControl->state() == CxeStillCaptureControl::Ready) {
                ready = true;
            }
        } else if (mode() == Cxe::VideoMode) {
            if (mVideoCaptureControl->state() == CxeVideoCaptureControl::Ready) {
                ready = true;
            }
        }
    }
    return ready;
}

/*!
    Prepare current capture control (CxeVideoCaptureControl in video mode,
    CxeStillCaptureControl in still image mode).
*/
void CxeEngineSymbian::doInit()
{
    CX_DEBUG_ENTER_FUNCTION();
    OstTrace0(camerax_performance, CXEENGINESYMBIAN_DOINIT_IN, "msg: e_CX_ENGINE_DO_INIT 1");

    mFilenameGenerator->init(mode());
    // load settings whenever we change mode or start camera or switch camera
    CxeSettingsImp *settingsImp = qobject_cast<CxeSettingsImp*>(mSettings);
    if (settingsImp) {
        settingsImp->loadSettings(mode());
    }

    if (mode() == Cxe::ImageMode) {
        mVideoCaptureControl->deinit();
        mStillCaptureControl->init();
    } else if (mode() == Cxe::VideoMode) {
        mStillCaptureControl->deinit();
        mVideoCaptureControl->init();
    }

    OstTrace0(camerax_performance, CXEENGINESYMBIAN_DOINIT_OUT, "msg: e_CX_ENGINE_DO_INIT 0");

    CX_DEBUG_EXIT_FUNCTION();
}

/*!
 * Returns camera mode.
 */
Cxe::CameraMode CxeEngineSymbian::mode() const
{
    return mCameraDeviceControl->mode();
}

/*!
 * Sets the camera mode.
 * \parama mode New camera mode
 */
void CxeEngineSymbian::setMode(Cxe::CameraMode mode)
{
    CX_DEBUG_ENTER_FUNCTION();
    mCameraDeviceControl->setMode(mode);
    CX_DEBUG_EXIT_FUNCTION();
}
/*!
    Check if we need to reserve camera.
*/
bool CxeEngineSymbian::reserveNeeded()
{
    // If camera device control is in Idle or pending release state,
    // we need to call reserve()
    return (mCameraDeviceControl->state() == CxeCameraDeviceControl::Idle ||
            mCameraDeviceControl->state() == CxeCameraDeviceControl::PendingRelease);
}

/*!
    Check if we need to prepare image/video capture.
*/
bool CxeEngineSymbian::initNeeded()
{
    bool result = false;

    if (mCameraDeviceControl->state() == CxeCameraDeviceControl::Ready) {
        if (mode() == Cxe::ImageMode) {
            if(mStillCaptureControl->state() == CxeStillCaptureControl::Uninitialized) {
                // We're in still image mode, camera is reserved and ready, but
                // we need to prepare still image control
                result = true;
            }
        } else if (mode() == Cxe::VideoMode) {
            if (mVideoCaptureControl->state() == CxeVideoCaptureControl::Idle ||
                mVideoCaptureControl->state() == CxeVideoCaptureControl::Initialized) {
                // We're in video mode, camera is reserved and ready, but
                // we need to prepare for video recording.
                result = true;
            }
        }
    }

    return result;
}

/*!
    Check if we need to start viewfinder.
*/
bool CxeEngineSymbian::startViewfinderNeeded()
{
    bool result = false;

    if (mViewfinderControl->state() != CxeViewfinderControl::Running) {
        if (mode() == Cxe::ImageMode &&
            mStillCaptureControl->state() == CxeStillCaptureControl::Ready) {
            // We're in still image mode and ready for capturing... we just need to
            // start viewfinder.
            result = true;
        } else if (mode() == Cxe::VideoMode &&
                   mVideoCaptureControl->state() == CxeVideoCaptureControl::Ready) {
            // We're in video mode and ready for capturing... we just need to
            // start viewfinder.
            result = true;
        }
    }

    return result;
}

void CxeEngineSymbian::initMode(Cxe::CameraMode cameraMode)
{
    CX_DEBUG_ENTER_FUNCTION();
    OstTrace0(camerax_performance, CXEENGINE_INITMODE_IN, "msg: e_CX_ENGINE_INIT_MODE 1");

    if (mode() == cameraMode) {
        CX_DEBUG(("initMode() called for current mode"));

        // We're already in the requested mode. However, it is possible
        // that we need to reserve and power on camera and/or prepare
        // the capture control.
        if (reserveNeeded()) {
            // Camera needs to be reserved. Initialization will continue
            // when we get the deviceReady() signal.
            CX_DEBUG(("initMode() - calling reserve()"));
            reserve();
        } else if (initNeeded()) {
            // Camera is reserved and ready, but we need to prepare still image control or
            // video capture control
            CX_DEBUG(("initMode() - calling doInit()"));
            doInit();
        } else if (startViewfinderNeeded()) {
            // Everything is ready and prepared, but we viewfinder is not yet running
            CX_DEBUG(("initMode() - calling viewfinder start()"));
            mViewfinderControl->start();
        } else {
            CX_DEBUG(("initMode() - no actions needed"));
            // Do nothing.
            // We are either already ready to capture or the we're pending
            // on prepare complete callback.
        }
    } else {
        CX_DEBUG(("initMode() called for mode switch"));

        // Mode switch
        mCameraDeviceControl->setMode(cameraMode);
        // stop the vf
        mViewfinderControl->stop();

        if (reserveNeeded()) {
            CX_DEBUG(("initMode() - calling reserve()"));
            reserve();
        } else if (mCameraDeviceControl->state() == CxeCameraDeviceControl::Ready) {
            CX_DEBUG(("initMode() - calling doInit()"));
            // Camera device is ready... we only need to prepare video or still
            // capture control, depending on current mode.
            doInit();
        } else {
            CX_DEBUG(("initMode() - no actions needed"));
            // Do nothing.
            // Camera device control is in Initializing state. Initialization will continue
            // when we get the deviceReady() callback.
        }
    }

    OstTrace0(camerax_performance, CXEENGINE_INITMODE_OUT, "msg: e_CX_ENGINE_INIT_MODE 0");
    CX_DEBUG_EXIT_FUNCTION();
}

void CxeEngineSymbian::reserve()
{
    CX_DEBUG_ENTER_FUNCTION();
    // Start reserving camera HW.
    mCameraDeviceControl->reserve();
    emit reserveStarted();
    CX_DEBUG_EXIT_FUNCTION();
}


/*!
* Saves current mode to the cenrep
*/
void CxeEngineSymbian::saveMode()
{
    CX_DEBUG_ENTER_FUNCTION();

    if (mCameraDeviceControl && mSettings) {
        try {
            mSettings->set(CxeSettingIds::CAMERA_MODE, mCameraDeviceControl->mode());
        } catch (CxeException &e) {
            CX_DEBUG(("Failed to save camera mode, error=%d", e.error()));
        }
    }

    CX_DEBUG_EXIT_FUNCTION();
}


/*!
* Initialize geotagging.
* Check if we are allowed to start the geotagging and if it's supported in current mode.
*/
void CxeEngineSymbian::initGeotagging()
{
    CX_DEBUG_ENTER_FUNCTION();
    OstTrace0(camerax_performance, CXEENGINE_START_GEO_IN, "msg: e_CX_ENGINE_START_GEOTAGGING 1");

    if (mGeoTaggingTrail && mSettings) {
        if (mode() == Cxe::ImageMode) {
            // Location trail is limited to image mode only for now.
            Cxe::GeoTaggingDisclaimer value =
                mSettings->get<Cxe::GeoTaggingDisclaimer>(
                    CxeSettingIds::GEOTAGGING_DISCLAIMER, Cxe::GeoTaggingDisclaimerDisabled);

            // we start location trail only when Geotagging First-time-use note is accepted by user.
            if (value == Cxe::GeoTaggingDisclaimerDisabled) {
                mGeoTaggingTrail->start();
            }
        } else {
            // Geotagging is not (yet) supported in video mode.
            mGeoTaggingTrail->stop();
        }
    }

    OstTrace0(camerax_performance, CXEENGINE_START_GEO_OUT, "msg: e_CX_ENGINE_START_GEOTAGGING 0");
    CX_DEBUG_EXIT_FUNCTION();
}

// End of file